我想从构造函数启动.NET 6 中发布的PeriodicTimer,并且在这个计时器中我想使用异步方法更新数据,我该如何处理它?
您可以创建一个调用此方法的异步方法,并从您想要启动计时器的任何代码中调用它。您可以在构造函数本身中调用该方法并存储它返回的任务,而无需等待它:
例如 :
class MyClass:IDisposable:IAsyncDisposable
{
PeriodicTimer _timer;
Task _timerTask;
CancellationTokenSource _cts;
public MyClass()
{
_cts=new CancellationTokenSource();
_timer=new PeriodicTimer(TimeSpan.FromSeconds(1));
_timerTask=HandleTimerAsync(_timer,_cts.Token);
}
public void Cancel()=>_cts.Cancel();
async Task HandleTimerAsync(PeriodicTimer timer,CancellationToken cancel=default)
{
try
{
while(await timer.WaitForNextTickAsync(cancel))
{
await Task.Run(()=>SomeHeavyJob(cancel),cancel);
}
}
catch(Exception exc)
{
//Handle the exception but don't propagate it
}
}
public async ValueTask DisposeAsync()
{
_timer.Dispose();
await _timerTask;
GC.SuppressFinalize(this);
}
}
Run Code Online (Sandbox Code Playgroud)
处理复杂的原因是定时器任务在调用后可能不会立即完成PeriodicTimer.Dispose()。该代码必须等待它完成。.NET 6DisposeAsync针对这种情况引入了。
Dispose并且DisposeAsync方法不应该抛出异常,这就是处理程序方法使用不传播异常的 catch 块的原因。否则,处理程序内部抛出的任何期望都将被重新抛出DisposeAsync,在该位置可能无法进行处理或记录,因为其他对象已自行释放。