首页 > 解决方案 > 将列表转换为带有或不带有 Task.Run 的任务列表?

问题描述

所以我知道 Task.Run 基本上使代码在线程池的新线程中运行。但是,如果我这样做有什么区别:

var tasks = new List<string>(){ "foo", "bar" }
   .Select(e => Task.Run(async () => await Process(e)))
   .ToList();

await Task.WhenAll(tasks);

对比

var tasks = new List<string>(){ "foo", "bar" }
   .Select(async e => await Process(e))
   .ToList();

await Task.WhenAll(tasks);

我的理解是,第二个片段在等待某个异步进程时一次只运行一个,而第一个片段实际上在线程池中的线程上并行运行它们?

标签: c#async-await

解决方案


这两种方法都会实例化一个任务列表,然后将await它们完成。通常它们之间应该没有区别,除非该ProcessAsync方法返回已经完成的任务(除非它同步运行,换句话说)。例如下面的实现:

async Task ProcessAsync(string arg)
{
     Thread.Sleep(1000); // Simulate some heavy calculation
     await Task.CompletedTask;
}

...阻塞当前线程 1000 毫秒,然后返回一个已完成的任务。此实现将仅与第一种方法(带Task.Run)并行运行,并将与第二种方法(不带Task.Run)按顺序运行。原因是创建任务成本高(所有工作都在创建过程中完成),等待任务成本低(任务已经完成)。基本上,Task.Run您可以将昂贵的工作转移到ThreadPool线程上。


推荐阅读