如果在一个线程池上执行一个定时的周期性的后台线程任务他是最好的选择,这个类是和线程池相关联的,它告诉线程池(ThreadPool)在指定的时间执行指定的方法
2.System.Timers.Timer
这个计时器经常和Window窗体一块使用,而且这个单线程处理的,从放入消息队列,再到提取,执行回调,都是一个线程完成
4.Windows.UI.Xaml.DispatcherTimer
这个类的本质就是System.Windows.Forms.Timer,微软设计目的是被用在Windows Store
这个类和System.Windows.Forms.Timer本质是相同的,但是这个类用在WPF中
public delegate void TimerCallback(object state);
我们在做开发的时候会遇到一种场景,当我们一个回调方法执行时间>period 设置的时间,就会导致上一个方法没有执行完,线程池就会新启动一个线程执行相同的方法,这样会产生多个线程同时执行一个方法,如何解决呢?我们可以在初始化Timer的时候给period参数设置为Timeout.Infinite,在回调方法中再次调用Timer.Change(3000,Timeout.Infinite) 并把peroid参数再次设置为Timeout.Infinite,下面代码我们对Timer进行了简单封装:
public class SafeTimer : IDisposable
{
#region Fields
private Timer innerTimer;
private TimerCallback safeCallback = null!;
private TimerCallback originalCallback = null!;
private int syncPoint;
private ManualResetEvent originalCallbackCompleteEvent = new ManualResetEvent(true);
#endregion
#region Constructors
public 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 methods
private 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. syncPoint=1 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 methods
public 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 Members
public void Dispose()
{
innerTimer.Dispose();
}
#endregion
}
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将任务放到线程池中执行!这节就到这里,希望对各位有收获。