Jim*_*Aho 7 c# application-lifecycle cancellation-token .net-core
我已经阅读了大部分关于.NET Core 3.1 中IHostApplicationLifetime和 CancellationToken 的文章,但我找不到这不起作用的原因。
我有一个简单的BackgroundService,如下所示:
public class AnotherWorker : BackgroundService
{
private readonly IHostApplicationLifetime _hostApplicationLifetime;
public AnotherWorker(IHostApplicationLifetime hostApplicationLifetime)
{
_hostApplicationLifetime = hostApplicationLifetime;
}
public override Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine($"Process id: {Process.GetCurrentProcess().Id}");
_hostApplicationLifetime.ApplicationStarted.Register(() => Console.WriteLine("Started"));
_hostApplicationLifetime.ApplicationStopping.Register(() => Console.WriteLine("Stopping"));
_hostApplicationLifetime.ApplicationStopped.Register(() => Console.WriteLine("Stopped"));
return Task.CompletedTask;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
Console.WriteLine("Executing");
return Task.CompletedTask;
}
public override async Task StopAsync(CancellationToken cancellationToken)
{
// This actually prints "Stop. IsCancellationRequested: False". Why?
Console.WriteLine($"Stop. IsCancellationRequested: {cancellationToken.IsCancellationRequested}");
await base.StopAsync(cancellationToken);
}
}
Run Code Online (Sandbox Code Playgroud)
默认添加了 ConsoleLifetime,它监听 Ctrl+C 和 SIGTERM 并通知 IHostApplicationLifetime。我猜 IHostApplicationLifetime 反过来应该取消所有 CancellationTokens?这是一篇关于这个主题的好文章。那么为什么上述代码片段的输出如下所示?
Hosting starting
Started
Hosting started
(sends SIGTERM with `kill -s TERM <process_id>`)
Applicationis shuting down...
Stop. IsCancellationRequested: False
Stopped
Hosting stopped
Run Code Online (Sandbox Code Playgroud)
我希望它记录 Stop. IsCancellationRequested: True
我希望能够将此令牌传递给其他服务调用,以便它们能够正常关闭。
Ste*_*ary 19
这里有很多不同的取消标记,以及几种不同的抽象(IHostApplicationLifetime, IHostedService, BackgroundService)。解开一切需要一段时间。您链接到的博客文章很棒,但没有详细介绍CancellationTokens。
首先,如果您打算使用BackgroundService,我建议您阅读代码。另外,我强烈建议不要覆盖StartAsyncand StopAsync; BackgroundService以非常特殊的方式使用这些。
IHostedService有两种方法。StartAsync启动服务运行(可能是异步的);它需要一个CancellationToken表示应该取消“开始”操作(我没有检查过,但我认为只有在应用程序几乎立即关闭时才会触发此令牌)。请注意,StartAsync需要在托管服务完成之前被视为处于“已启动”或“正在运行”状态。同样,StopAsync停止服务(可能是异步的)。StopAsync在应用程序开始正常关闭时调用。正常关闭期间有一个超时,之后应用程序开始其“我现在很认真”关闭。该CancellationToken用于StopAsync表示“正常”变为“我现在是认真的”的转变。所以' 在正常关闭超时窗口期间设置。
如果您使用BackgroundService的,而不是IHostedService直接(像大多数人一样),你会得到一个不同的 CancellationToken在ExecuteAsync。这个是在BackgroundService.StopAsync被调用时设置的——即,当应用程序开始正常关闭时。因此,它大致相当于IHostApplicationLifetime.ApplicationStopping,但仅限于单个托管服务。您可以期望在BackgroundWorker.ExecuteAsync CancellationToken设置后不久IHostApplicationLifetime.ApplicationStopping设置。
请注意,所有这些CancellationTokens 代表不同的东西:
IHostedService.StartAsync的CancellationToken意思是“中止此服务的启动”。IHostedService.StopAsync的CancellationToken意思是‘停止此服务,现在,你在宽限期出局’。IHostApplicationLifetime.ApplicationStopping 意思是“整个应用程序的正常关闭序列已经开始;请大家停止你正在做的事情”。
IHostedService.StopAsync方法都会被调用。BackgroundService.ExecuteAsync's 的CancellationToken意思是“停止这项服务”。一个有趣的注意事项是BackgroundService类型通常不会看到“我现在是认真的”信号;他们只看到“停止这项服务”的信号。这可能是因为由 a 表示的“我现在是认真的”信号CancellationToken有些令人困惑。
如果您查看的代码Host,则关闭序列在其关闭序列中使用了更多取消标记:
IHost.StopAsync具有CancellationToken “停止不应该再优雅”的意思。CancellationToken基于超时的超时。CancellationToken被解雇,如果任何的IHost.StopAsync令牌被解雇或者如果定时器经过。所以这也意味着“停止不应再优雅”。IHostApplicationLifetime.StopApplication,取消IHostApplicationLifetime.ApplicationStopping CancellationToken.StopAsyncIHostedService,传递“停止不应再优雅”的标记。
BackgroundService类型都有自己的CancellationToken(ExecuteAsync在启动期间传递给),并且这些取消标记由StopAsync.IHostApplicationLifetime.NotifyStopped,取消IHostApplicationLifetime.ApplicationStopped CancellationToken。我为“不再优雅”信号计数 3(一个传入,一个计时器,一个将这两个信号连接起来),加上 2 on IHostApplicationLifetime,每个加上 1 BackgroundService,用于5 + n关闭期间使用的总共取消令牌。:)
| 归档时间: |
|
| 查看次数: |
3751 次 |
| 最近记录: |