c# - 我可以在单线程 C# 控制台应用程序中安全地使用 async void 异步处理队列中的多个项目吗?

标签 c# .net async-await

我和我的团队支持多个后台工作控制台应用程序,这些应用程序同步处理来自队列的消息。

目前,当队列中的消息数量超过特定阈值时,我们使用 docker 启动应用程序的新实例来处理多条消息。

我们正在讨论并行处理这些消息的替代方法,一位队友建议在 while 循环中使用顶级 async void 方法来处理消息。

看起来它会起作用,因为它类似于使用 async void 作为事件处理程序的基于 UI 的应用程序。

但是,我个人从未编写过后台 worker 以这种方式并行处理多个消息,并且想知道是否有人有这样做的经验,如果有,是否存在我们没有的“陷阱”正在思考。

以下是建议解决方案的简化版本:

static async void Main(string[] args)
{
    while (true)
    {
        TopLevelHandler(await ReceiveMessage());
    }
}

static async void TopLevelHandler(object message)
{
    await DoAsyncWork(message);
}

static async Task<object> ReceiveMessage()
{
    //fetch message from queue
    return new object();
}

static async Task DoAsyncWork(object message)
{
    //processing here
}

最佳答案

Can I safely use async void...

这取决于你所说的“安全”是什么意思。 async void方法具有特定的行为,因此如果您喜欢这些行为,那么 async void 就可以了。

  1. async void 操作无法等待,因此您不知道它们何时完成。如果您需要在终止程序之前等待所有挂起的异步操作完成,那么 async void 不适合您。
  2. async void 操作中引发的未处理异常将在 async void 方法启动时捕获的 SynchronizationContext 上重新引发。由于您有一个控制台应用程序,因此没有 SynchronizationContext,因此错误将在 ThreadPool 上抛出。这意味着您的应用程序将引发 AppDomain.UnhandledException 事件,然后崩溃。如果您要求应用程序不随机崩溃,那么 async void 就不适合您。

async void 方法最初是为了使 async 事件处理程序成为可能而发明的。在现代实践中,这仍然是它们的主要用途。

使async void成为一个有趣选择的一个利基场景是,您有一个工作流程,当它完成时,它必须启动另一个工作流程。如果踢球对于应用程序的连续流程至关重要,并且踢球失败将使您的应用程序处于挂起状态,那么将这种失败升级为进程崩溃事件是有意义的。可以说,崩溃的程序比挂起的程序相对要好。您可以看到针对此场景使用 async void 的两个示例 herehere 。在第二个示例中,async void 是传递给 ThreadPool.QueueUserWorkItem 方法的 lambda,确保 async void 不会捕获任何未知环境SynchronizationContext

关于c# - 我可以在单线程 C# 控制台应用程序中安全地使用 async void 异步处理队列中的多个项目吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73754807/

相关文章:

.net - 对以下示例中的单一职责原则感到困惑

JavaScript 多个函数的顺序执行

python - OCPP Python 包文档

c# - 如何从 ApiController 中的 StringContent 对象读取 JSON?

c# - ManipulationCompleted 事件未在 Button 上触发

c# - 如何使用 JSON.Net 反序列化为匿名类型?

c# - 从类库项目启动 WPF 窗口

c# - 如何增加 Linq2Entities 中的超时时间?

C#/.NET(核心): Is the type system safe enough to prevent SQL injections?

.net - 如何下载数据库到本地