Dot-Net-Core

Environment.Exit 後託管服務未終止

  • May 31, 2022

我有一個帶有託管服務的 .NET core 3.1 應用程序,它在 Windows 上作為控制台應用程序執行。

如果出現錯誤,我會嘗試使用Environment.Exit(1).

現在的問題是,如果在 any inEnviroment.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解決過這個問題。

如果出現錯誤,我會嘗試使用 Environment.Exit(1) 終止工作人員。

我建議根本不要使用Environment.Exit。相反,通過注入IHostApplicationLifetime和呼叫StopApplication. 這將為stoppingToken您的每個後台服務觸發,如果它們忽略它,它們將在超時後被強制終止。

引用自:https://stackoverflow.com/questions/59879271