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

时间:2021-07-24 00:17:15

Just this - How do you add a timer to a C# console application? It would be great if you could supply some example coding.

就是这样 - 如何在C#控制台应用程序中添加计时器?如果您能提供一些示例编码,那就太棒了。

7 个解决方案

#1


106  

That's very nice, however in order to simulate some time passing we need to run a command that takes some time and that's very clear in second example.

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

However, the style of using a for loop to do some functionality forever takes a lot of device resources and instead we can use the Garbage Collector to do some thing like that.

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

We can see this modification in the code from the same book CLR Via C# Third Ed.

我们可以在同一本书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();
   }
}

#2


64  

Use the System.Threading.Timer class.

使用System.Threading.Timer类。

System.Windows.Forms.Timer is designed primarily for use in a single thread usually the Windows Forms UI thread.

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

There is also a System.Timers class added early on in the development of the .NET framework. However it is generally recommended to use the System.Threading.Timer class instead as this is just a wrapper around System.Threading.Timer anyway.

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

It is also recommended to always use a static (shared in VB.NET) System.Threading.Timer if you are developing a Windows Service and require a timer to run periodically. This will avoid possibly premature garbage collection of your timer object.

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

Here's an example of a timer in a console application:

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

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 
    }
}

From the book CLR Via C# by Jeff Richter. By the way this book describes the rationale behind the 3 types of timers in Chapter 23, highly recommended.

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

#3


20  

Here is the code to create a simple one second timer tick:

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

  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);
          }
      }
  }

And here is the resulting output:

以下是结果输出:

    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

EDIT: It is never a good idea to add hard spin loops into code as they consume CPU cycles for no gain. In this case that loop was added just to stop the application from closing, allowing the actions of the thread to be observed. But for the sake of correctness and to reduce the CPU usage a simple Sleep call was added to that loop.

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

#4


11  

Lets Have A little Fun

让我们玩得开心

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("                  DIFFUSE 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();
        }
    }
}

#5


9  

Or using Rx, short and sweet:

或者使用Rx,短而甜:

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

for (; ; ) { }
}

#6


4  

You can also use your own timing mechanisms if you want a little more control, but possibly less accuracy and more code/complexity, but I would still recommend a timer. Use this though if you need to have control over the actual timing thread:

如果你想要更多的控制,你可以使用自己的计时机制,但可能更少的准确性和更多的代码/复杂性,但我仍然会建议一个计时器。如果您需要控制实际的时序线程,请使用此方法:

private void ThreadLoop(object callback)
{
    while(true)
    {
        ((Delegate) callback).DynamicInvoke(null);
        Thread.Sleep(5000);
    }
}

would be your timing thread(modify this to stop when reqiuired, and at whatever time interval you want).

将是你的计时线程(修改此设置,以便在需要时停止,并在您想要的任何时间间隔)。

and to use/start you can do:

并使用/启动你可以做:

Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));

t.Start((Action)CallBack);

Callback is your void parameterless method that you want called at each interval. For example:

回调是您希望在每个时间间隔调用的无参数无效方法。例如:

private void CallBack()
{
    //Do Something.
}

#7


1  

You can also create your own (if unhappy with the options available).

您也可以创建自己的(如果对可用选项不满意)。

Creating your own Timer implementation is pretty basic stuff.

创建自己的Timer实现是非常基本的东西。

This is an example for an application that needed COM object access on the same thread as the rest of my codebase.

这是一个应用程序的示例,该应用程序需要在与我的代码库的其余部分相同的线程*问COM对象。

/// <summary>
/// Internal timer for window.setTimeout() and window.setInterval().
/// This is to ensure that async calls always run on the same thread.
/// </summary>
public class Timer : IDisposable {

    public void Tick()
    {
        if (Enabled && Environment.TickCount >= nextTick)
        {
            Callback.Invoke(this, null);
            nextTick = Environment.TickCount + Interval;
        }
    }

    private int nextTick = 0;

    public void Start()
    {
        this.Enabled = true;
        Interval = interval;
    }

    public void Stop()
    {
        this.Enabled = false;
    }

    public event EventHandler Callback;

    public bool Enabled = false;

    private int interval = 1000;

    public int Interval
    {
        get { return interval; }
        set { interval = value; nextTick = Environment.TickCount + interval; }
    }

    public void Dispose()
    {
        this.Callback = null;
        this.Stop();
    }

}

You can add events as follows:

您可以按如下方式添加事件:

Timer timer = new Timer();
timer.Callback += delegate
{
    if (once) { timer.Enabled = false; }
    Callback.execute(callbackId, args);
};
timer.Enabled = true;
timer.Interval = ms;
timer.Start();
Window.timers.Add(Environment.TickCount, timer);

To make sure the timer works you need to create an endless loop as follows:

要确保计时器正常工作,您需要创建一个无限循环,如下所示:

while (true) {
     // Create a new list in case a new timer
     // is added/removed during a callback.
     foreach (Timer timer in new List<Timer>(timers.Values))
     {
         timer.Tick();
     }
}

#1


106  

That's very nice, however in order to simulate some time passing we need to run a command that takes some time and that's very clear in second example.

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

However, the style of using a for loop to do some functionality forever takes a lot of device resources and instead we can use the Garbage Collector to do some thing like that.

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

We can see this modification in the code from the same book CLR Via C# Third Ed.

我们可以在同一本书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();
   }
}

#2


64  

Use the System.Threading.Timer class.

使用System.Threading.Timer类。

System.Windows.Forms.Timer is designed primarily for use in a single thread usually the Windows Forms UI thread.

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

There is also a System.Timers class added early on in the development of the .NET framework. However it is generally recommended to use the System.Threading.Timer class instead as this is just a wrapper around System.Threading.Timer anyway.

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

It is also recommended to always use a static (shared in VB.NET) System.Threading.Timer if you are developing a Windows Service and require a timer to run periodically. This will avoid possibly premature garbage collection of your timer object.

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

Here's an example of a timer in a console application:

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

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 
    }
}

From the book CLR Via C# by Jeff Richter. By the way this book describes the rationale behind the 3 types of timers in Chapter 23, highly recommended.

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

#3


20  

Here is the code to create a simple one second timer tick:

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

  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);
          }
      }
  }

And here is the resulting output:

以下是结果输出:

    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

EDIT: It is never a good idea to add hard spin loops into code as they consume CPU cycles for no gain. In this case that loop was added just to stop the application from closing, allowing the actions of the thread to be observed. But for the sake of correctness and to reduce the CPU usage a simple Sleep call was added to that loop.

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

#4


11  

Lets Have A little Fun

让我们玩得开心

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("                  DIFFUSE 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();
        }
    }
}

#5


9  

Or using Rx, short and sweet:

或者使用Rx,短而甜:

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

for (; ; ) { }
}

#6


4  

You can also use your own timing mechanisms if you want a little more control, but possibly less accuracy and more code/complexity, but I would still recommend a timer. Use this though if you need to have control over the actual timing thread:

如果你想要更多的控制,你可以使用自己的计时机制,但可能更少的准确性和更多的代码/复杂性,但我仍然会建议一个计时器。如果您需要控制实际的时序线程,请使用此方法:

private void ThreadLoop(object callback)
{
    while(true)
    {
        ((Delegate) callback).DynamicInvoke(null);
        Thread.Sleep(5000);
    }
}

would be your timing thread(modify this to stop when reqiuired, and at whatever time interval you want).

将是你的计时线程(修改此设置,以便在需要时停止,并在您想要的任何时间间隔)。

and to use/start you can do:

并使用/启动你可以做:

Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));

t.Start((Action)CallBack);

Callback is your void parameterless method that you want called at each interval. For example:

回调是您希望在每个时间间隔调用的无参数无效方法。例如:

private void CallBack()
{
    //Do Something.
}

#7


1  

You can also create your own (if unhappy with the options available).

您也可以创建自己的(如果对可用选项不满意)。

Creating your own Timer implementation is pretty basic stuff.

创建自己的Timer实现是非常基本的东西。

This is an example for an application that needed COM object access on the same thread as the rest of my codebase.

这是一个应用程序的示例,该应用程序需要在与我的代码库的其余部分相同的线程*问COM对象。

/// <summary>
/// Internal timer for window.setTimeout() and window.setInterval().
/// This is to ensure that async calls always run on the same thread.
/// </summary>
public class Timer : IDisposable {

    public void Tick()
    {
        if (Enabled && Environment.TickCount >= nextTick)
        {
            Callback.Invoke(this, null);
            nextTick = Environment.TickCount + Interval;
        }
    }

    private int nextTick = 0;

    public void Start()
    {
        this.Enabled = true;
        Interval = interval;
    }

    public void Stop()
    {
        this.Enabled = false;
    }

    public event EventHandler Callback;

    public bool Enabled = false;

    private int interval = 1000;

    public int Interval
    {
        get { return interval; }
        set { interval = value; nextTick = Environment.TickCount + interval; }
    }

    public void Dispose()
    {
        this.Callback = null;
        this.Stop();
    }

}

You can add events as follows:

您可以按如下方式添加事件:

Timer timer = new Timer();
timer.Callback += delegate
{
    if (once) { timer.Enabled = false; }
    Callback.execute(callbackId, args);
};
timer.Enabled = true;
timer.Interval = ms;
timer.Start();
Window.timers.Add(Environment.TickCount, timer);

To make sure the timer works you need to create an endless loop as follows:

要确保计时器正常工作,您需要创建一个无限循环,如下所示:

while (true) {
     // Create a new list in case a new timer
     // is added/removed during a callback.
     foreach (Timer timer in new List<Timer>(timers.Values))
     {
         timer.Tick();
     }
}