如果完全异步,我的任务是否长时间运行?

时间:2014-03-28 08:57:10

标签: c# .net multithreading task-parallel-library async-await

考虑这样的代码:

private static async Task ProcessSomethingAsync()
{
    while (true)
    {
        var message = await GetMessageAsync();
        await WriteAsync(message);
    }
}

考虑 GetMessageAsync WriteAsync 方法利用异步IO。

想象一下,我有几个(从2到N)这样的任务,只要应用程序存在就可以生存。 我认为,由于循环中的代码是完全异步的,因此最好不要在启动此类任务时使用LongRunning选项,以便我们能够利用ThreadPool而不是为每个任务创建线程。

这是正确的还是我错过了什么?

2 个答案:

答案 0 :(得分:6)

  

最好不要在启动此类任务时使用LongRunning选项,这样我们就可以利用ThreadPool而不是为每个任务创建线程。

当您运行async代码时,不应指定LongRunning。如果你这样做,那么(截至今天的实现),线程池将启动一个新线程,只是为了运行async代码的第一部分。一旦您的代码产生await,该新线程将被释放,其余代码将在常规线程池线程上运行。因此,LongRunning通常会对async代码起反作用。

我有一篇关于为什么StartNew is dangerous的博客文章,而我(简要地)涵盖了该帖子中的所有TaskCreationOptions

  

AttachedToParent不应该用于异步任务,因此不会出现。 DenyChildAttach应始终与异步任务一起使用(提示:如果您还不知道,那么StartNew不是您需要的工具)。 DenyChildAttach由Task.Run传递。 HideScheduler在某些非常模糊的调度方案中可能很有用,但对于异步任务通常应该避免使用。这只留下LongRunning和PreferFairness,这两个优化提示只应在应用程序分析后指定。我经常看到LongRunning特别被滥用。在绝大多数情况下,线程池将在0.5秒内调整为任何长时间运行的任务 - 没有 LongRunning标志。最有可能的是,你真的不需要它。

答案 1 :(得分:1)

是的,指定LongRunning可能会允许创建更多线程,因为您告诉调度程序您的任务将长时间占用一个线程。

异步方法恰恰相反,他们释放线程来做其他事情而不会阻塞。