哪个网站买域名便宜,长沙做网站最好的公司有哪些,网站流程图设计工具,做网站诈钱.NET的FCL中提供了几个计时器#xff0c;大多数初学者都不清楚他们有什么不同#xff0c;那我们这节来剖解一下每个计时器的本质#xff1a;1.System.Threading.Timer如果在一个线程池上执行一个定时的周期性的后台线程任务他是最好的选择#xff0c;这个类是和线程池相关联….NET的FCL中提供了几个计时器大多数初学者都不清楚他们有什么不同那我们这节来剖解一下每个计时器的本质1.System.Threading.Timer如果在一个线程池上执行一个定时的周期性的后台线程任务他是最好的选择这个类是和线程池相关联的它告诉线程池(ThreadPool)在指定的时间执行指定的方法2.System.Timers.Timer这个类是对System.Threading.Timer类的封装所以他两本质上是相同在这里推荐使用System.Threading.Timer计时器3.System.Windows.Forms.Timer这个计时器经常和Window窗体一块使用而且这个单线程处理的从放入消息队列再到提取执行回调都是一个线程完成4.Windows.UI.Xaml.DispatcherTimer这个类的本质就是System.Windows.Forms.Timer微软设计目的是被用在Windows Store5.System.Windows.Threading.DispatcherTimer这个类和System.Windows.Forms.Timer本质是相同的但是这个类用在WPF中我们以System.Threading.Timer为例来介绍一下推荐大家在项目中用这个计时器。我们可以看出有4个构造函数我们分别讲解一下每个参数的用途1、callback表示由线程池线程回调的方法他是一个委托定义如下public delegate void TimerCallback(object state);2、state 参数表示每次调用回调方法时传递的参数如果没有则为null3、dueTime表示在调用回调方法之前等待多少毫秒4、period表示调用callback的时间间隔我们在做开发的时候会遇到一种场景当我们一个回调方法执行时间period 设置的时间就会导致上一个方法没有执行完线程池就会新启动一个线程执行相同的方法这样会产生多个线程同时执行一个方法如何解决呢我们可以在初始化Timer的时候给period参数设置为Timeout.Infinite在回调方法中再次调用Timer.Change(3000,Timeout.Infinite) 并把peroid参数再次设置为Timeout.Infinite下面代码我们对Timer进行了简单封装:public class SafeTimer : IDisposable
{#region Fieldsprivate Timer innerTimer;private TimerCallback safeCallback null!;private TimerCallback originalCallback null!;private int syncPoint;private ManualResetEvent originalCallbackCompleteEvent new ManualResetEvent(true);#endregion#region Constructorspublic SafeTimer(TimerCallback callback){InitializeCallback(callback);innerTimer new Timer(safeCallback);}public SafeTimer(TimerCallback callback, object state, long dueTime, long period){InitializeCallback(callback);innerTimer new Timer(safeCallback, state, dueTime, period);}public SafeTimer(TimerCallback callback, object state, uint dueTime, uint period){InitializeCallback(callback);innerTimer new Timer(safeCallback, state, dueTime, period);}public SafeTimer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period){InitializeCallback(callback);innerTimer new Timer(safeCallback, state, dueTime, period);}public SafeTimer(TimerCallback callback, object state, int dueTime, int period){InitializeCallback(callback);innerTimer new Timer(safeCallback, state, dueTime, period);}#endregion#region Private methodsprivate void InitializeCallback(TimerCallback callback){originalCallback callback;safeCallback new TimerCallback(NonReentryCallback);}private void NonReentryCallback(object? state){//set syncPoint to 1 if the original value is 0. syncPoint1 indicates a method is executing.if (Interlocked.CompareExchange(ref syncPoint, 1, 0) 0){originalCallbackCompleteEvent.Reset();try{originalCallback(state);}catch { }finally{originalCallbackCompleteEvent.Set();Interlocked.Exchange(ref syncPoint, 0);}}}#endregion#region Public methodspublic bool Change(long dueTime, long period){return innerTimer.Change(dueTime, period);}public bool Change(int dueTime, int period){return innerTimer.Change(dueTime, period);}public bool Change(TimeSpan dueTime, TimeSpan period){return innerTimer.Change(dueTime, period);}public bool Change(uint dueTime, uint period){return innerTimer.Change(dueTime, period);}public void Stop(){innerTimer.Change(Timeout.Infinite, Timeout.Infinite);originalCallbackCompleteEvent.WaitOne();}public bool Stop(int milliseconds){innerTimer.Change(Timeout.Infinite, Timeout.Infinite);return originalCallbackCompleteEvent.WaitOne(milliseconds);}#endregion#region IDisposable Memberspublic void Dispose(){innerTimer.Dispose();}#endregion
}我们做个简单的Demo来做个测试internal class Program
{private static SafeTimer safeTimer null!;static void Main(string[] args){safeTimer new SafeTimer(WriteLine, string.Empty, 2000, Timeout.Infinite);Console.ReadLine();}public static void WriteLine(object? state){Thread.Sleep(3000);Console.WriteLine(Hello DateTime.Now.ToString(yyyy-MM-dd hh:mm:ss fff));safeTimer.Change(2000, Timeout.Infinite);}
}运行结果如下我们看到执行是按照线性执行没有并行执行达到我们预期效果本质上是将任务调用ThreadPool.QueueUserWorkItem将任务放到线程池中执行这节就到这里希望对各位有收获。