培训
计时器
.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 类可用于按指定时间间隔持续调用委托。 此外,还可以使用此类计划按指定时间间隔对委托进行单次调用。 该委托在 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 是另一个可在多线程环境中使用的计时器,该计时器默认情况下在 ThreadPool 线程上引发事件。
在创建 System.Timers.Timer 对象时,可以指定引发 Elapsed 事件的时间间隔。 使用 Enabled 属性指示计时器是否应引发 Elapsed 事件。 如果仅需在经过指定时间间隔后引发一次 Elapsed 事件,请将 AutoReset 设置为 false
。 AutoReset 属性的默认值为 true
,表示将按 Interval 属性定义的时间间隔定期引发 Elapsed 事件。
有关更多信息和示例,请参见System.Timers.Timer。
通过 System.Threading.PeriodicTimer 类,可以等待指定间隔的各滴答声,从而在调用 PeriodicTimer.WaitForNextTickAsync 后执行工作。
创建 System.Threading.PeriodicTimer 对象时,指定 TimeSpan,用于确定计时器的每个滴答声之间的时间长度。 可以直接在作用域中执行工作,等待 WaitForNextTickAsync 以使计时器提前指定间隔,而不是像在之前的计时器类中那样传递回调或设置事件处理程序。
WaitForNextTickAsync 方法返回 ValueTask<bool>
;成功触发计时器时为 true
,通过调用 PeriodicTimer.Dispose 取消计时器时为 false
。 WaitForNextTickAsync(可选)接受 CancellationToken,当请求取消时,这将导致 TaskCanceledException。
有关详细信息,请参阅 System.Threading.PeriodicTimer。