如何将计时器添加到C#控制台应用程序

Joh*_*ler 127 c# console timer

就是这样 - 如何在C#控制台应用程序中添加计时器?如果你能提供一些示例编码会很棒.

小智 116

这非常好,但是为了模拟一些时间的流逝,我们需要运行一个需要一些时间的命令,这在第二个例子中非常清楚.

但是,使用for循环来执行某些功能的风格永远需要大量的设备资源,而我们可以使用垃圾收集器来做这样的事情.

我们可以在同一本书CLR Via C#Third Ed的代码中看到这种修改.

using System;
using System.Threading;

public static class Program {

   public static void Main() {
      // Create a Timer object that knows to call our TimerCallback
      // method once every 2000 milliseconds.
      Timer t = new Timer(TimerCallback, null, 0, 2000);
      // Wait for the user to hit <Enter>
      Console.ReadLine();
   }

   private static void TimerCallback(Object o) {
      // Display the date/time when this method got called.
      Console.WriteLine("In TimerCallback: " + DateTime.Now);
      // Force a garbage collection to occur for this demo.
      GC.Collect();
   }
}
Run Code Online (Sandbox Code Playgroud)

  • @Ralph Willgoss,为什么选择GC.Collect(); 是必须的? (9认同)
  • 哈立德,这非常有帮助.谢谢.console.readline()和GC.Collect正是我所需要的. (3认同)
  • @Puchacz我看不出调用`GC.Collect()`的意义。没有什么可收集的。如果在Console.ReadLine();之后调用了GC.KeepAlive(t),那将是有道理的。 (2认同)
  • 第一次回调后终止 (2认同)
  • @Khalid Al Hajami“但是,使用 for 循环执行某些功能的方式永远需要大量设备资源,而我们可以使用垃圾收集器来执行类似的操作。” 这绝对是无稽之谈的垃圾。垃圾收集器完全无关紧要。您是否从书本上复制了此内容但不明白您复制的内容? (2认同)

Ash*_*Ash 65

使用System.Threading.Timer类.

System.Windows.Forms.Timer主要设计用于单个线程,通常是Windows窗体UI线程.

在.NET框架的开发早期还添加了一个System.Timers类.但是,通常建议使用System.Threading.Timer类,因为这只是System.Threading.Timer的包装器.

如果您正在开发Windows服务并且需要定期运行计时器,还建议始终使用静态(在VB.NET中共享)System.Threading.Timer.这将避免可能过早的垃圾收集您的计时器对象.

以下是控制台应用程序中的计时器示例:

using System; 
using System.Threading; 
public static class Program 
{ 
    public static void Main() 
    { 
       Console.WriteLine("Main thread: starting a timer"); 
       Timer t = new Timer(ComputeBoundOp, 5, 0, 2000); 
       Console.WriteLine("Main thread: Doing other work here...");
       Thread.Sleep(10000); // Simulating other work (10 seconds)
       t.Dispose(); // Cancel the timer now
    }
    // This method's signature must match the TimerCallback delegate
    private static void ComputeBoundOp(Object state) 
    { 
       // This method is executed by a thread pool thread 
       Console.WriteLine("In ComputeBoundOp: state={0}", state); 
       Thread.Sleep(1000); // Simulates other work (1 second)
       // When this method returns, the thread goes back 
       // to the pool and waits for another task 
    }
}
Run Code Online (Sandbox Code Playgroud)

来自Jeff Richter的CLR Via C#一书.顺便说一下,本书描述了第23章中3种计时器背后的基本原理,强烈推荐.


jus*_*sij 21

这是创建简单的一秒计时器滴答的代码:

  using System;
  using System.Threading;

  class TimerExample
  {
      static public void Tick(Object stateInfo)
      {
          Console.WriteLine("Tick: {0}", DateTime.Now.ToString("h:mm:ss"));
      }

      static void Main()
      {
          TimerCallback callback = new TimerCallback(Tick);

          Console.WriteLine("Creating timer: {0}\n", 
                             DateTime.Now.ToString("h:mm:ss"));

          // create a one second timer tick
          Timer stateTimer = new Timer(callback, null, 0, 1000);

          // loop here forever
          for (; ; )
          {
              // add a sleep for 100 mSec to reduce CPU usage
              Thread.Sleep(100);
          }
      }
  }
Run Code Online (Sandbox Code Playgroud)

这是结果输出:

    c:\temp>timer.exe
    Creating timer: 5:22:40

    Tick: 5:22:40
    Tick: 5:22:41
    Tick: 5:22:42
    Tick: 5:22:43
    Tick: 5:22:44
    Tick: 5:22:45
    Tick: 5:22:46
    Tick: 5:22:47
Run Code Online (Sandbox Code Playgroud)

编辑:将硬自旋循环添加到代码中永远不是一个好主意,因为它们消耗CPU周期而没有增益.在这种情况下,添加循环只是为了阻止应用程序关闭,允许观察线程的操作.但为了正确起见并减少CPU使用,在该循环中添加了一个简单的Sleep调用.

  • for(;;){}导致100%的cpu使用率. (7认同)
  • 令人惊讶的是,有多少人关注for循环是否应该是while循环以及为什么CPU达到100%.谈论想念树木!方位角,我个人想知道一段时间(1)与无限循环有什么不同?当然,编写CLR编译器优化器的人会确保这两个代码构造创建完全相同的CLR代码吗? (3认同)

小智 16

让我们有一点乐趣

using System;
using System.Timers;

namespace TimerExample
{
    class Program
    {
        static Timer timer = new Timer(1000);
        static int i = 10;

        static void Main(string[] args)
        {            
            timer.Elapsed+=timer_Elapsed;
            timer.Start(); Console.Read();
        }

        private static void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            i--;

            Console.Clear();
            Console.WriteLine("=================================================");
            Console.WriteLine("                  DEFUSE THE BOMB");
            Console.WriteLine(""); 
            Console.WriteLine("                Time Remaining:  " + i.ToString());
            Console.WriteLine("");        
            Console.WriteLine("=================================================");

            if (i == 0) 
            {
                Console.Clear();
                Console.WriteLine("");
                Console.WriteLine("==============================================");
                Console.WriteLine("         B O O O O O M M M M M ! ! ! !");
                Console.WriteLine("");
                Console.WriteLine("               G A M E  O V E R");
                Console.WriteLine("==============================================");

                timer.Close();
                timer.Dispose();
            }

            GC.Collect();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 10

或者使用Rx,短而甜:

static void Main()
{
Observable.Interval(TimeSpan.FromSeconds(10)).Subscribe(t => Console.WriteLine("I am called... {0}", t));

for (; ; ) { }
}
Run Code Online (Sandbox Code Playgroud)

  • 非常不可读,反对最佳实践.它看起来很棒但不应该在生产中使用,因为一些ppl将自己去wtf和poo. (6认同)
  • 同意@ppumkin,这违反了许多坚实的原则. (2认同)
  • Reactive Extensions (Rx) 已经有 2 年没有积极开发了。此外,这些示例没有上下文且令人困惑。鲜为人知的图表或流程示例。 (2认同)