namespace System.Threading
{
public static class Timeout
{
public const int Infinite = -1;
public static readonly TimeSpan InfiniteTimeSpan;
}
}
namespace System.Threading
{
public delegate void TimerCallback(object state);
}
public sealed class Timer : MarshalByRefObject, IDisposable
{
public Timer(TimerCallback callback);
public Timer(TimerCallback callback, object state, int dueTime, int period);
public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period);
public Timer(TimerCallback callback, object state, uint dueTime, uint period);
public Timer(TimerCallback callback, object state, long dueTime, long period);
public bool Change(int dueTime, int period);
public bool Change(TimeSpan dueTime, TimeSpan period);
public bool Change(uint dueTime, uint period);
public bool Change(long dueTime, long period);
public bool Dispose(WaitHandle notifyObject);
public void Dispose();
}
指定定时器每次触发时,执行的方法。
通过这个参数为回调方法提供实参。定时器每次回调时,都会取最新的object参数的值。
定时器第一次触发前等待的时长。如果该值为负值,则此计时器永远不会启动。如果该值为0,则计时器立刻触发第一次回调。如果为正数,则dueTime毫秒后,计时器触发第一次回调。
定时器每次触发回调的时间间隔。该值等于0或小于0时,则计时器只触发一次回调(dueTime >= 0)或一次都不触发(dueTime < 0)。该值大于0时,每隔period毫秒,会触发一次回调。
计数器启动后,dueTime毫秒后触发第一次回调,第一次回调后,每隔period毫秒后,触发一次回调。
只有当dueTime不小于0时,Timer才可能执行回调。period若小于或等于0,计时器最多执行一次回调。
构造Timer实例
Timer timer = new Timer(new TimerCallback((state) =>{}));
timer = new Timer(new TimerCallback((state) => { }), null, Timeout.Infinite, Timeout.Infinite);
timer = new Timer(new TimerCallback((state) => { }), null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
使用Change()启动计时器
timer.Change(100,1000);
Timer timer = new Timer(new TimerCallback((state) =>{}),null,100,1000);
我们可以利用Change()随时暂停,重启计时器,也可以改变计时器的第一次执行方法之前等待的时间量(截止时间)以及此后的执行期间等待的时间量(时间周期)。
定时器会在回调方法执行完毕后,再过指定的时间,再进行下一次回调。
static void Main(string[] args)
{
Timer timer = null;
timer = new Timer((state) =>
{
Thread.Sleep(2000);
Console.WriteLine("执行定时任务");
timer.Change(1000, Timeout.Infinite);
}, null, 1000, Timeout.Infinite);
Console.ReadLine();
}
这个示例,会每隔3秒打印一次“执行定时任务”。
using System;
using System.Threading;
class TimerExample
{
static void Main()
{
// Create an AutoResetEvent to signal the timeout threshold in the
// timer callback has been reached.
var autoEvent = new AutoResetEvent(false);
var statusChecker = new StatusChecker(10);
// Create a timer that invokes CheckStatus after one second,
// and every 1/4 second thereafter.
Console.WriteLine("{0:h:mm:ss.fff} Creating timer.\n",
DateTime.Now);
var stateTimer = new Timer(statusChecker.CheckStatus,
autoEvent, 1000, 250);
// When autoEvent signals, change the period to every half second.
autoEvent.WaitOne();
stateTimer.Change(0, 500);
Console.WriteLine("\nChanging period to .5 seconds.\n");
// When autoEvent signals the second time, dispose of the timer.
autoEvent.WaitOne();
stateTimer.Dispose();
Console.WriteLine("\nDestroying timer.");
}
}
class StatusChecker
{
private int invokeCount;
private int maxCount;
public StatusChecker(int count)
{
invokeCount = 0;
maxCount = count;
}
// This method is called by the timer delegate.
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
Console.WriteLine("{0} Checking status {1,2}.",
DateTime.Now.ToString("h:mm:ss.fff"),
(++invokeCount).ToString());
if(invokeCount == maxCount)
{
// Reset the counter and signal the waiting thread.
invokeCount = 0;
autoEvent.Set();
}
}
}
// The example displays output like the following:
// 11:59:54.202 Creating timer.
//
// 11:59:55.217 Checking status 1.
// 11:59:55.466 Checking status 2.
// 11:59:55.716 Checking status 3.
// 11:59:55.968 Checking status 4.
// 11:59:56.218 Checking status 5.
// 11:59:56.470 Checking status 6.
// 11:59:56.722 Checking status 7.
// 11:59:56.972 Checking status 8.
// 11:59:57.223 Checking status 9.
// 11:59:57.473 Checking status 10.
//
// Changing period to .5 seconds.
//
// 11:59:57.474 Checking status 1.
// 11:59:57.976 Checking status 2.
// 11:59:58.476 Checking status 3.
// 11:59:58.977 Checking status 4.
// 11:59:59.477 Checking status 5.
// 11:59:59.977 Checking status 6.
// 12:00:00.478 Checking status 7.
// 12:00:00.980 Checking status 8.
// 12:00:01.481 Checking status 9.
// 12:00:01.981 Checking status 10.
//
// Destroying timer.
当我们不想再执行定时任务时,如果不在意任务执行的次数,可以直接Dispose();如果在意的话,可以先利用Change( )暂停向线程池排队线程,然后利用Dispose(WaitHandle waitHandle)确定线程池里面所有的回调线程都执行完毕,再继续后续流程。
如果回调方法中调用了Timer的成员,可能会出现调用了一个对象的Dispose()后再次调用该对象的其他成员导致抛出异常的情况,对于Timer则是ObjectDisposeException,我们最好处理一下该可能的异常。
When a timer is no longer needed, use the Dispose method to free the resources held by the timer. Note that callbacks can occur after the Dispose() method overload has been called, because the timer queues callbacks for execution by thread pool threads. You can use the Dispose(WaitHandle) method overload to wait until all callbacks have completed.
The callback method executed by the timer should be reentrant, because it is called on ThreadPool threads. The callback can be executed simultaneously on two thread pool threads if the timer interval is less than the time required to execute the callback, or if all thread pool threads are in use and the callback is queued multiple times.
原文:https://www.cnblogs.com/LiuwayLi/p/14857358.html