计时器
.NET 提供三种可在多线程环境中使用的计时器:
- System.Threading.Timer,用于按固定时间间隔在 ThreadPool 线程上执行单个回叫方法。
- System.Timers.Timer,默认情况下按固定时间间隔在 ThreadPool 线程上引发事件。
- System.Threading.PeriodicTimer,它允许调用方在等待计时器的各滴答声后执行工作。
备注
某些 .NET 实现可能包含其他计时器:
- System.Windows.Forms.Timer:一种 Windows 窗体组件,按固定时间间隔触发事件。 该组件没有用户界面,专门用于单线程环境。
- System.Web.UI.Timer:一种 ASP.NET 组件,按固定时间间隔执行异步或同步网页回发。
- System.Windows.Threading.DispatcherTimer:集成到 Dispatcher 队列中的计时器,该队列按指定时间间隔和指定优先级进行处理。
System.Threading.Timer 类
System.Threading.Timer 类可用于按指定时间间隔持续调用委托。 此外,还可以使用此类计划按指定时间间隔对委托进行单次调用。 该委托在 ThreadPool 线程上执行。
在创建 System.Threading.Timer 对象时,需指定定义回叫方法的 TimerCallback 委托、传递到该回叫的可选状态对象、首次调用该回叫前的延迟时间以及两次回叫调用之间的时间间隔。 若要取消挂起的计时器,请调用 Timer.Dispose 方法。
以下示例创建一个计时器,该计时器在一秒(1000 毫秒)后首次调用提供的委托,之后每两秒调用一次该委托。 示例中的状态对象用于计算调用该委托的次数。 当调用委托至少达 10 次时,计时器将停止。
using namespace System;
using namespace System::Threading;
ref class TimerState
{
public:
int counter;
};
ref class Example
{
private:
static Timer^ timer;
public:
static void TimerTask(Object^ state)
{
Console::WriteLine("{0:HH:mm:ss.fff}: starting a new callback.", DateTime::Now);
TimerState^ timerState = dynamic_cast<TimerState^>(state);
Interlocked::Increment(timerState->counter);
}
static void Main()
{
TimerCallback^ tcb = gcnew TimerCallback(&TimerTask);
TimerState^ state = gcnew TimerState();
state->counter = 0;
timer = gcnew Timer(tcb, state, 1000, 2000);
while (state->counter <= 10)
{
Thread::Sleep(1000);
}
timer->~Timer();
Console::WriteLine("{0:HH:mm:ss.fff}: done.", DateTime::Now);
}
};
int main()
{
Example::Main();
}
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
private static Timer timer;
static void Main(string[] args)
{
var timerState = new TimerState { Counter = 0 };
timer = new Timer(
callback: new TimerCallback(TimerTask),
state: timerState,
dueTime: 1000,
period: 2000);
while (timerState.Counter <= 10)
{
Task.Delay(1000).Wait();
}
timer.Dispose();
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: done.");
}
private static void TimerTask(object timerState)
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: starting a new callback.");
var state = timerState as TimerState;
Interlocked.Increment(ref state.Counter);
}
class TimerState
{
public int Counter;
}
}
Imports System.Threading
Module Program
Private Timer As Timer
Sub Main(args As String())
Dim StateObj As New TimerState
StateObj.Counter = 0
Timer = New Timer(New TimerCallback(AddressOf TimerTask), StateObj, 1000, 2000)
While StateObj.Counter <= 10
Task.Delay(1000).Wait()
End While
Timer.Dispose()
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: done.")
End Sub
Private Sub TimerTask(ByVal StateObj As Object)
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: starting a new callback.")
Dim State As TimerState = CType(StateObj, TimerState)
Interlocked.Increment(State.Counter)
End Sub
Private Class TimerState
Public Counter As Integer
End Class
End Module
有关更多信息和示例,请参见System.Threading.Timer。
System.Timers.Timer 类
System.Timers.Timer 是另一个可在多线程环境中使用的计时器,该计时器默认情况下在 ThreadPool 线程上引发事件。
在创建 System.Timers.Timer 对象时,可以指定引发 Elapsed 事件的时间间隔。 使用 Enabled 属性指示计时器是否应引发 Elapsed 事件。 如果仅需在经过指定时间间隔后引发一次 Elapsed 事件,请将 AutoReset 设置为 false
。 AutoReset 属性的默认值为 true
,表示将按 Interval 属性定义的时间间隔定期引发 Elapsed 事件。
有关更多信息和示例,请参见System.Timers.Timer。
System.Threading.PeriodicTimer 类
通过 System.Threading.PeriodicTimer 类,可以等待指定间隔的各滴答声,从而在调用 PeriodicTimer.WaitForNextTickAsync 后执行工作。
创建 System.Threading.PeriodicTimer 对象时,指定 TimeSpan,用于确定计时器的每个滴答声之间的时间长度。 可以直接在作用域中执行工作,等待 WaitForNextTickAsync 以使计时器提前指定间隔,而不是像在之前的计时器类中那样传递回调或设置事件处理程序。
WaitForNextTickAsync 方法返回 ValueTask<bool>
;成功触发计时器时为 true
,通过调用 PeriodicTimer.Dispose 取消计时器时为 false
。 WaitForNextTickAsync(可选)接受 CancellationToken,当请求取消时,这将导致 TaskCanceledException。
有关详细信息,请参阅 System.Threading.PeriodicTimer。