![](/img/trans.png)
[英]Is there a way to manually start BackgroundService in Asp.Net core 3.1
[英]Why is IsCancellationRequested not set to true on stopping a BackgroundService in .NET Core 3.1?
我已經閱讀了大多數關於 .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);
}
}
默認添加 ConsoleLifetime,它監聽 Ctrl+C 和 SIGTERM 並通知 IHostApplicationLifetime。 我猜 IHostApplicationLifetime 應該反過來取消所有 CancellationTokens 嗎? 這是一篇關於這個主題的好文章。 那么為什么上面代碼片段中的 output 如下?
Hosting starting
Started
Hosting started
(sends SIGTERM with `kill -s TERM <process_id>`)
Applicationis shuting down...
Stop. IsCancellationRequested: False
Stopped
Hosting stopped
我希望它記錄Stop. IsCancellationRequested: True
Stop. IsCancellationRequested: True
我希望能夠將此令牌傳遞給其他服務調用,以便它們能夠正常關閉。
這里有很多不同的取消標記,以及幾個不同的抽象( IHostApplicationLifetime
、 IHostedService
、 BackgroundService
)。 解開一切需要一段時間。 您鏈接到的博客文章很棒,但 go 並沒有詳細介紹CancellationToken
。
首先,如果您要使用BackgroundService
,我建議您閱讀代碼。 另外,我強烈建議不要覆蓋StartAsync
和StopAsync
; BackgroundService
以一種非常特殊的方式使用它們。
IHostedService
有兩種方法。 StartAsync
啟動服務運行(可能異步); 它需要一個CancellationToken
來指示應該取消“開始”操作(我沒有檢查過,但我認為只有當應用程序幾乎立即關閉時才會觸發此令牌)。 請注意,在“已啟動”或“正在運行” StartAsync
中考慮托管服務之前,需要完成StartAsync。 同樣, StopAsync
停止服務(可能是異步的)。 當應用程序開始正常關閉時調用StopAsync
。 正常關閉期間有一個超時,之后應用程序開始“我現在是認真的”關閉。 StopAsync
的CancellationToken
表示從“優雅”到“我現在很認真”的過渡。 所以在正常關機超時 window 期間沒有設置它。
如果您直接使用BackgroundService
而不是IHostedService
(像大多數人一樣),您會在ExecuteAsync
中獲得不同的CancellationToken
。 這是在調用BackgroundService.StopAsync
時設置的 - 即,當應用程序開始正常關閉時。 所以它大致相當於IHostApplicationLifetime.ApplicationStopping
,但僅限於單個托管服務。 您可以期望在設置IHostApplicationLifetime.ApplicationStopping
后不久設置BackgroundWorker.ExecuteAsync
CancellationToken
。
請注意,所有這些CancellationToken
都代表不同的東西:
IHostedService.StartAsync
的CancellationToken
表示“中止此服務的啟動”。IHostedService.StopAsync
的CancellationToken
表示“立即停止此服務;您已超出寬限期”。IHostApplicationLifetime.ApplicationStopping
的意思是“整個應用程序的正常關閉序列已經開始;每個人都請停止你正在做的事情”。
IHostedService.StopAsync
方法。BackgroundService.ExecuteAsync
的CancellationToken
表示“停止此服務”。 有趣的是, BackgroundService
類型通常看不到“我現在很認真”的信號。 他們只看到“停止此服務”的信號。 這可能是因為CancellationToken
所代表的“我現在是認真的”信號有些令人困惑。
如果您查看Host
的代碼,則關閉序列在其關閉序列中使用了更多取消標記:
IHost.StopAsync
采用CancellationToken
表示“停止不應再優雅” 。CancellationToken
的超時。CancellationToken
,如果IHost.StopAsync令牌被觸發或計時器已過, IHost.StopAsync
觸發。 所以這個也意味着“停止不應該再優雅”。IHostApplicationLifetime.StopApplication
,它取消了IHostApplicationLifetime.ApplicationStopping
CancellationToken
。IHostedService
調用StopAsync
,傳遞“停止應該不再是優雅的”令牌。
BackgroundService
類型都有自己的CancellationToken
(在啟動期間傳遞給ExecuteAsync
),並且這些取消令牌由StopAsync
取消。IHostApplicationLifetime.NotifyStopped
,它取消了IHostApplicationLifetime.ApplicationStopped
CancellationToken
。 我為“不再優雅”信號計數 3(一個傳入,一個計時器,一個鏈接這兩個),加上IHostApplicationLifetime
上的 2 個,每個BackgroundService
加上 1 個,在關機期間總共使用了5 + n
取消令牌。 :)
傳遞給StopAsync
的CancellationToken
指示BackgroundService
是否必須執行正常關閉或硬關閉。
您使用kill -s TERM
停止該進程,以便它發送SIGTERM
信號要求應用程序正常關閉。 因此IsCancellationRequested
屬性仍為 false。
要將令牌傳遞給其他服務調用,您必須提供自己的CancellationToken
。 您可以使用CancellationTokenSource
來管理令牌的創建和取消。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.