如何在构造函数中使用PeriodicTimer?

Jac*_*ack 2 timer .net-6.0

我想从构造函数启动.NET 6 中发布的PeriodicTimer,并且在这个计时器中我想使用异步方法更新数据,我该如何处理它?

Pan*_*vos 8

您可以创建一个调用此方法的异步方法,并从您想要启动计时器的任何代码中调用它。您可以在构造函数本身中调用该方法并存储它返回的任务,而无需等待它:

例如 :

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,在该位置可能无法进行处理或记录,因为其他对象已自行释放。