考虑这样的代码:
private static async Task ProcessSomethingAsync()
{
while (true)
{
var message = await GetMessageAsync();
await WriteAsync(message);
}
}
考虑 GetMessageAsync 和 WriteAsync 方法利用异步IO。
想象一下,我有几个(从2到N)这样的任务,只要应用程序存在就可以生存。 我认为,由于循环中的代码是完全异步的,因此最好不要在启动此类任务时使用LongRunning选项,以便我们能够利用ThreadPool而不是为每个任务创建线程。
这是正确的还是我错过了什么?
答案 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可能会允许创建更多线程,因为您告诉调度程序您的任务将长时间占用一个线程。
异步方法恰恰相反,他们释放线程来做其他事情而不会阻塞。