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

Max*_*Max 0 .net c# multithreading task-parallel-library async-await

考虑这样的代码:

private static async Task ProcessSomethingAsync()
{
    while (true)
    {
        var message = await GetMessageAsync();
        await WriteAsync(message);
    }
}
Run Code Online (Sandbox Code Playgroud)

考虑GetMessageAsyncWriteAsync方法利用异步IO.

想象一下,我有几个(从2到N)这样的任务,只要应用程序存在就可以存活.在我看来,由于循环内的代码是完全异步的,所以最好不要在启动这些任务时使用LongRunning选项,这样我们就可以利用ThreadPool而不是为每个Task创建线程.

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

Ste*_*ary 6

在我开始执行此类任务时最好不要使用LongRunning选项,这样我们就可以利用ThreadPool而不是为每个Task创建线程.

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

我有一篇关于为什么StartNew是危险的博客文章,我(简要地)涵盖了TaskCreationOptions该帖子中的所有内容:

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