您需要创建一个实现
IHostedService
. 这个接口只定义了两个方法,StartAsync,它在应用程序启动时调用,并且
StopAsync
当它终止时调用。
您需要将其注册为托管服务:
services.AddHostedService<TimedHostedService>();
小心使用
AddHostedService
,
不是
AddSingleton
. 如果你使用
地址单例
运行时不知道在适当的时候调用StartAsync和StopAsync。
文章
Background tasks with hosted services in ASP.NET Core
演示如何使用计时器实现服务:
internal class TimedHostedService : IHostedService, IDisposable
{
private readonly ILogger _logger;
private Timer _timer;
public TimedHostedService(ILogger<TimedHostedService> logger)
{
_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Timed Background Service is starting.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(10));
return Task.CompletedTask;
}
private void DoWork(object state)
{
_logger.LogInformation("Timed Background Service is working.");
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Timed Background Service is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
这段代码没有什么特别有趣的地方-只要在
StartAsync
被叫停了
停止异步
取消长时间运行的任务
当运行库需要回收或停止时,它将调用
停止异步
方法在所有托管服务上,等待它们正常完成,然后警告它们立即取消。过一段时间后,它将继续并终止应用程序或回收它。
这个
cancellationToken
参数用于指示服务应立即停止。通常,这意味着您必须编写自己的代码来检查它,警告自己的任务终止,等待所有任务完成等等,与代码类似
shown in this article
不过,这基本上是样板文件,这就是为什么
BackgroundService
类可用于创建只需实现
ExecuteAsync(CancellationToken)
. 启动和停止该任务由
BackgroundService
,例如:
public class PollingService : BackgroundService
{
private readonly ILogger _logger;
public PollingService(ILogger<PollingService> logger)
{
_logger = logger;
}
protected async override Task ExecuteAsync(
CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
await DoSomething(cancellationToken);
await Task.Delay(1000,cancellationToken);
}
catch (Exception ex)
{
_logger.LogError(ex,
$"Error occurred executing {nameof(workItem)}.");
}
}
_logger.LogInformation("Queued Hosted Service is stopping.");
}
}
在这种情况下
Task.Delay()
一旦运行时引发取消标记,它本身将被取消。
DoSomething()
本身应该以检查取消标记的方式实现,例如将其传递给任何接受它作为参数的异步方法,测试
IsCancellationRequested
属性在每个循环中退出,并将其退出。
例如:
protected async override Task ExecuteAsync(
CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
foreach (var ext in GetExtensions())
{
//Oops, time to cancel
if(cancellationToken.IsCancellationRequested)
{
break;
}
//Otherwise, keep working
ext.Status = StatusType.Available;
}
await Task.Delay(1000,cancellationToken);
}
catch (Exception ex)
{
...
}
}
_logger.LogInformation("Hosted Service is stopping.");
}