如何向 C# 控制台应用程序添加计时器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/186084/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you add a timer to a C# console application
提问by Johan Bresler
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# 控制台应用程序添加计时器?如果您能提供一些示例编码,那就太好了。
采纳答案by Khalid Al Hajami
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();
}
}
回答by Ash
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.
还有一个 System.Timers 类是在 .NET 框架开发的早期添加的。然而,通常建议使用 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 种定时器背后的基本原理,强烈推荐。
回答by jussij
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 调用。
回答by mattlant
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:
回调是您想要在每个时间间隔调用的 void 无参数方法。例如:
private void CallBack()
{
//Do Something.
}
回答by Yonatan Zetuny
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 (; ; ) { }
}
回答by Steven de Salas
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();
}
}
回答by Real Caz
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(" 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();
}
}
}
回答by XvXLuka222
There you have it :)
你有它 :)
public static void Main()
{
SetTimer();
Console.WriteLine("\nPress the Enter key to exit the application...\n");
Console.WriteLine("The application started at {0:HH:mm:ss.fff}", DateTime.Now);
Console.ReadLine();
aTimer.Stop();
aTimer.Dispose();
Console.WriteLine("Terminating the application...");
}
private static void SetTimer()
{
// Create a timer with a two second interval.
aTimer = new System.Timers.Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Console.WriteLine("The Elapsed event was raised at {0:HH:mm:ss.fff}",
e.SignalTime);
}
回答by kokabi
In C# 5.0+ and .NET Framework 4.5+ you can use async/await:
在 C# 5.0+ 和 .NET Framework 4.5+ 中,您可以使用 async/await:
async void RunMethodEvery(Action method, double seconds)
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(seconds));
method();
}
}