使用异步线程的退出代码退出应用程序
Posted
技术标签:
【中文标题】使用异步线程的退出代码退出应用程序【英文标题】:Exit the application with exit code from async thread 【发布时间】:2021-09-24 00:02:09 【问题描述】:我的 .NET5 Web API 项目(除了 REST)监听 Telegram 消息。目标很简单:
当用户发送 exit 消息时 - 使用退出代码 8 终止应用 当消息处理程序抛出 SeriousException - 使用退出代码 8 终止应用程序不幸的是,由于消息轮询的异步性质,我正在努力实现这一目标。我在 GitHub 中准备了一个示例项目:https://github.com/chris-rutkowski/AsExPoC。
我在 Stack Overflow 上发现了许多类似的主题,但没有什么真正适合我,而且大量建议的解决方案(一些 AsyncHelpers 等)似乎有点矫枉过正。我正在考虑将Thread.CurrentThread
传递给服务并以某种方式抛出异常,但我不知道如何,或者它是否可能发生,即使它是最佳实践。我对 C#+.NET 了解不多,但是在 Swift (ios) 中,我会很容易地解决它,只需 3 行,包括大括号:
DispatchQueue.main.async
throw ForcedExitException()
这是我精简的 .NET5 Web Api,您可以在 repo 中找到。
Program.cs
public class Program
public static int Main(string[] args)
try
var host = CreateHostBuilder(args).Build();
var service = host.Services.GetRequiredService<DummyService>();
service.Run();
// other services are running too - I cannot just wait for DummyService to throw the exception
host.Run();
return 0;
catch (ForcedExitException)
return 8;
catch (Exception ex)
return 1;
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
webBuilder.UseStartup<Startup>();
);
DummyService.cs
public class DummyService
private readonly DummyMessenger _dummyMessenger;
public DummyService()
_dummyMessenger = new DummyMessenger();
public async void Run()
_dummyMessenger.StartReceiving();
_dummyMessenger.Add(async (_, message) =>
Console.WriteLine($"received message message");
await Task.Delay(50);
if (message == "exit")
throw new ForcedExitException();
);
我的期望:
Exited with error code 8
这是我在控制台中看到的:
Exited with error code 134, with the following stacktrace
Unhandled exception. AsExPoC.ForcedExitException: Exception of type 'AsExPoC.ForcedExitException' was thrown.
at AsExPoC.DummyService.<>c.<Run>b__2_0(Object _, String message) in /Users/chris/Developer/Projects/AsExPoC/AsExPoC/DummyService.cs:line 36
at AsExPoC.DummyMessenger.StartReceiving() in /Users/chris/Developer/Projects/AsExPoC/AsExPoC/DummyMessenger.cs:line 27
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__140_1(Object state)
at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
感谢反馈。
【问题讨论】:
我没有考虑太多,但你试过Environment.Exit(Int32)
@TheGeneral 感谢您的关注。它不会改变任何东西。我在 GitHub 上创建了示例项目:github.com/chris-rutkowski/AsExPoC。同时,我将更新我的问题以使其更简单。
【参考方案1】:
我将首先将您长期运行的服务移至IHostedService
,如果服务停止,则强制主机停止;
public class DummyService : BackgroundService
private readonly IHostApplicationLifetime lifetime;
public DummyService(IHostApplicationLifetime lifetime)
this.lifetime = lifetime;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
try
while (true)
//...
catch (Exception)
Environment.ExitCode = 8;
lifetime.StopApplication();
然后你可以从你的 main 方法中返回Environment.ExitCode
,或者将它保留为void
return。
【讨论】:
以上是关于使用异步线程的退出代码退出应用程序的主要内容,如果未能解决你的问题,请参考以下文章