StartAsync
方法中,计算了下一个整数分钟的时间,然后使用 System.Threading.Timer
类创建定时器,并将首次触发时间设为该时间。在 InsertDB2Async
方法中,我们定义了要执行的操作,然后使用 await Task.Delay(1000)
模拟异步操作的等待时间。最后,我们重新计算下一个整数分钟的时间,并使用 Change
方法设置定时器的下一次触发时间。
需要注意的是,InsertDB2Async
方法是异步方法,但是我们使用的是 async void
定义方法。在实际应用中,应该使用 async Task
定义异步方法,以避免出现无法捕获的异常。另外,System.Threading.Timer
类的回调方法是在另一个线程上执行的,因此在操作期间需要注意线程安全。
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
public class MyTimerHostedService : IHostedService, IDisposable
{
private Timer _timer;
public Task StartAsync(CancellationToken cancellationToken)
{
// 计算下一个整分钟的时间,并设置定时器的首次触发时间
var now = DateTime.Now;
var nextMinute = now.AddMinutes(1);
var target = nextMinute.AddSeconds(-nextMinute.Second);
var delay = (int)(target - now).TotalMilliseconds;
_timer = new Timer(InsertDB2Async, null, delay, 60000);
return Task.CompletedTask;
}
private async void InsertDB2Async(object state)
{
try
{
// 在这里写你要执行的代码
Console.WriteLine($"[{DateTime.Now}] Hello, world!");
// 等待异步操作完成
await Task.Delay(1000);
}
finally
{
// 计算下一个整分钟的时间,并设置定时器的下一次触发时间
var now = DateTime.Now;
var nextMinute = now.AddMinutes(1);
var target = nextMinute.AddSeconds(-nextMinute.Second);
var delay = (int)(target - now).TotalMilliseconds;
_timer.Change(delay, 60000);
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
_timer.Dispose();
return Task.CompletedTask;
}
public void Dispose()
{
_timer.Dispose();
}
}
-
使用Task.Delay方法的重载版本,将等待时间和取消标志作为参数传入,可以及时响应取消请求。
-
使用CancellationToken.Register方法注册取消回调函数,避免忘记取消定时器。
-
将计算下一个整分钟的时间的代码封装为一个单独的方法,提高代码复用性。
public class MyTimerHostedService : IHostedService, IDisposable
{
private Timer _timer;
private CancellationTokenSource _cts;
public Task StartAsync(CancellationToken cancellationToken)
{
_cts = new CancellationTokenSource();
_timer = new Timer(async state =>
{
try
{
// 在这里写你要执行的代码
Console.WriteLine($"[{DateTime.Now}] Hello, world!");
// 等待异步操作完成
await Task.Delay(GetDelayTime(), _cts.Token);
}
finally
{
// 重新设置定时器的下一次触发时间
_timer.Change(GetDelayTime(), Timeout.Infinite);
}
}, null, GetDelayTime(), Timeout.Infinite);
cancellationToken.Register(() =>
{
_cts.Cancel();
_timer.Dispose();
});
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_cts.Cancel();
_timer.Dispose();
return Task.CompletedTask;
}
public void Dispose()
{
_cts.Dispose();
_timer.Dispose();
}
private TimeSpan GetDelayTime()
{
var now = DateTime.Now;
var nextMinute = now.AddMinutes(1);
var target = nextMinute.AddSeconds(-nextMinute.Second);
return target - now;
}
}
文章评论