gpt4 book ai didi

c# - 为什么在调用 IHost.StopAsync 时会调用两次 IHostedService.StopAsync?

转载 作者:行者123 更新时间:2023-12-03 15:56:11 29 4
gpt4 key购买 nike

给定以下使用通用主机的 .NET Core 2.2 控制台应用程序:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace SimpleGenericHost
{
class SimpleHostedService : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Service started");
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Service stopped");
return Task.CompletedTask;
}
}

class Program
{
static async Task Main(string[] args)
{
var host = new HostBuilder()
.ConfigureServices(services =>
{
services.AddHostedService<SimpleHostedService>();
})
.Build();

var runTask = host.RunAsync();
await Task.Delay(5000);
await host.StopAsync();
await runTask;

}
}
}

当你运行它时,输出如下:
Service started
Application started. Press Ctrl+C to shut down.
Hosting environment: Production
Content root path: C:\projects\ConsoleApps\SimpleGenericHost\bin\Debug\netcoreapp2.2\
Service stopped
Service stopped

如您所见 SimpleHostedService.StopAsync被调用两次。为什么?

这是预期的吗?我错过了什么吗?是否有另一种方法可以阻止 IHostedService.StopAsync 的主机只调用一次?

最佳答案

因为它被调用了两次 - 一次是在延迟之后,另一次是在服务实际停止时。它并不意味着在 RunAsync 时被调用用来。

要在超时后停止,请使用带有超时的 CancellationTokenSource 并将其 token 传递给 RunAsync :

var timeoutCts=new CancellationTokenSource(5000);

await host.RunAsync(timeoutCts.Token);

说明

StopAsync 不会停止服务,它用于通知服务需要停止。当应用程序停止时,它由托管服务基础结构本身调用。

.NET Core 是开源的,这意味着您可以查看 the RunAsync source . RunAsync启动主机,然后等待终止:
await host.StartAsync(token);

await host.WaitForShutdownAsync(token);

WaitForShutdownAsync方法从控制台或显式调用 IHostApplicationLifetime.StopApplication 来监听终止请求。 .当这种情况发生时,它会调用 StopAsync本身:
await waitForStop.Task;

// Host will use its default ShutdownTimeout if none is specified.
await host.StopAsync();

您应该使用 StartAsync而不是 RunAsync如果您打算自己管理应用程序的生命周期。

但是,在这种情况下,您只需要在超时时停止应用程序。您可以通过将取消 token 传递给 RunAsync 来轻松做到这一点。仅在超时后触发,通过 CancellationTokenSource(int)构造函数:
var timeoutCts=new CancellationTokenSource(5000);

await host.RunAsync(timeoutCts.Token);

关于c# - 为什么在调用 IHost.StopAsync 时会调用两次 IHostedService.StopAsync?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57426145/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com