【问题标题】:Why is AsyncContext needed when using async/await with a console application?为什么在控制台应用程序中使用 async/await 时需要 AsyncContext?
【发布时间】:2015-05-04 14:22:47
【问题描述】:

我正在控制台应用程序中调用异步方法。我不希望应用程序在启动后不久退出,即在等待任务完成之前。看来我可以这样做:

internal static void Main(string[] args)
{
    try
    {
        Task.WaitAll(DoThisAsync());
    }
    catch (Exception ex)
    {
        Console.Error.WriteLine(ex);
        throw;
    }
}

internal static async Task DoThisAsync()
{
    //...
}

但根据Stephen Cleary's article,我似乎不能这样做,而是应该为异步创建某种上下文以在完成时返回(例如AsyncContext)。

上面的代码虽然有效,但它在Task.WaitAll(DoThisAsync());之后返回主线程,那为什么我需要使用自定义上下文?

【问题讨论】:

  • 当你使用线程池时可能会发生这种情况。线程池线程是后台线程,只有主线程是前台。 UI 应用程序将有一个主循环,不允许它们在某些事情发生之前退出,而控制台应用程序通常没有这个循环。所以,如果你不阻塞你的主线程等待某些东西,你的应用程序将简单地退出,你在线程池上所做的工作将会消失。不过我不确定。
  • 正如@StephenCleary 提到的,这只是一种偏好。你如何阻塞线程并不重要,你只需要注意,如果你不以某种方式管理该线程,你的应用程序将退出(即使你的其他线程没有完成)
  • @Brandon 好吧,这很重要。它们的功能不同,但当然可以使用任何一种方法编写工作程序。

标签: c# .net asynchronous async-await console-application


【解决方案1】:

这不是必需的;这只是我的偏好。

您可以在Main 内同步阻止任务(使用Wait/Result/WaitAll)。语义略有不同;特别是,如果异步代码失败,则Wait/Result/WaitAll 会将异常包装在AggregateException 中,而AsyncContext 不会。

另外,AsyncContext 特殊对待主线程;它不会将延续发送到线程池,而是将它们发送回该主线程(默认情况下;您始终可以使用ConfigureAwait(false) 来避免这种情况)。如果我正在编写“概念验证”控制台应用程序,我发现这很有用,因为 AsyncContext 的行为与 UI 上下文非常相似。

但归根结底,这只是一个偏好问题。

【讨论】:

  • 我必须记住,拥有 AsyncContext 的一个关键目的是模拟 UI。
  • 如果您所做的只是阻止AggregateException,为什么AsyncContext 需要这么多代码?我看到一个TaskScheduler、TaskQueue (BlockingQueue)、TaskFactory 和AsyncContextSynchronizationContext。我看到一个 AsyncContextThread,它说它执行 AsyncContext 的操作。我想我的意思是这里似乎发生了很多事情,但我还没有找到关于实际发生的事情的好文章。我没有时间尝试破译正在发生的事情。
  • @crush:不,AsyncContext 基本上充当消息循环,只有在所有异步操作完成后才退出。在一般情况下,我不建议将其用作Result 的替代品。对于控制台的Main 方法,使用ResultAsyncContext 就可以了;在一般情况下,您应该使用await 而不是Result,绝对不能使用AsyncContext
  • @StephenCleary 感谢您的回复。我刚刚找到(阅读)你的2013 article on Async/Await best practices,它真的把事情弄清楚了。这很好地总结了我的情况:“对于那些“涉足”异步编程的程序员来说,这是一个特别常见的问题,只转换他们应用程序的一小部分并将其包装在同步 API 中,因此应用程序的其余部分与更改隔离。" 似乎AsyncContext 的存在可以帮助程序员进行过渡?
  • @crush:这是一种可能性,但出于重入的考虑,我仍然不推荐它。我有一个更新的article on async brownfield development,您可能会觉得有用。
猜你喜欢
  • 1970-01-01
  • 2015-08-10
  • 2015-10-12
  • 1970-01-01
  • 2017-10-26
  • 2019-02-26
  • 2015-06-30
  • 1970-01-01
相关资源
最近更新 更多