我有一个带有托管服务的 .NET core 3.1 应用程序,它在 Windows 上作为控制台应用程序运行。
如果出现错误,我会尝试使用 Environment.Exit(1)
终止工作人员.
现在的问题是,如果 Enviroment.Exit()
在任何 await
之前调用在 ExecuteAsync
,应用程序不会终止。它记录 Waiting for the host to be disposed. Ensure all 'IHost' instances are wrapped in 'using' blocks.
然后无限期挂起。
当我在调用 Enviroment.Exit()
之前等待任何事情时它也记录了这一点,但它按预期终止。
这是我能想出的重现问题的最简单的代码。NotTerminatingWorker
永远挂起,TerminatingWorker
终止。唯一的区别是微小的 Task.Delay
:
public class Program {
public static async Task Main(string[] args) {
using var host = CreateHostBuilder(args).Build();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) {
return Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) => { services.AddHostedService<NotTerminatingWorker>(); });
}
}
public class NotTerminatingWorker : BackgroundService {
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
Environment.Exit(1);
}
}
public class TerminatingWorker : BackgroundService {
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
await Task.Delay(1);
Environment.Exit(1);
}
}
我希望两者的行为方式相同,但显然情况并非如此。
对此的任何解释将不胜感激!
更新 :应用程序应该能够作为控制台应用程序和 Windows 服务运行。如果它崩溃,则需要非零返回码才能重新启动它。
显然 Windows 不会重新启动以代码 0 退出的服务。
最佳答案
我相信您看到的行为是 .NET Core 运行时启动方式的副作用:它调用 ExecuteAsync
对于每个后台工作人员,然后等待它完成。所以一个同步的ExecuteAsync
可能会导致问题。我用过Task.Run
解决这个问题。
In case of an error I'm trying to terminate the worker with Environment.Exit(1).
我建议不要使用
Environment.Exit
一点也不。相反,通过注入(inject) IHostApplicationLifetime
来控制关闭。并调用 StopApplication
.这将触发 stoppingToken
对于您的每个后台服务,如果它们忽略它,它们将在超时后被强制终止。
关于.net-core - Environment.Exit 后托管服务未终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59879271/