C# 将列表转换为包含或不包含任务的任务列表。是否运行?

C# 将列表转换为包含或不包含任务的任务列表。是否运行?,c#,async-await,C#,Async Await,所以我知道Task.Run基本上使代码在线程池中的一个新线程中运行。但如果我这样做有什么区别: var tasks = new List<string>(){ "foo", "bar" } .Select(e => Task.Run(async () => await Process(e))) .ToList(); await Task.WhenAll(tasks); var tasks=newlist(){“foo”,“bar”} .Select(e=>

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

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

await Task.WhenAll(tasks);
var tasks=newlist(){“foo”,“bar”}
.Select(e=>Task.Run(异步()=>await进程(e)))
.ToList();
等待任务。何时(任务);
vs

var tasks=newlist(){“foo”,“bar”}
.选择(异步e=>等待进程(e))
.ToList();
等待任务。何时(任务);

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

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

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

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

您正在指定
async
,但您没有在任何地方执行
wait
。代码将给您一个生成警告。为了更好地理解,我建议您在测试程序的
Process()
方法中添加一行代码
Console.WriteLine(Thread.CurrentThread.ManagedThreadId)
并查看两个版本的输出。第二个版本将给出编译警告,并且确实是同步的。这是否回答了您的问题?作为旁注,根据
流程方法应命名为
ProcessAsync
。是的,否则它们仍然会在彼此之后执行。
async Task ProcessAsync(string arg)
{
     Thread.Sleep(1000); // Simulate some heavy calculation
     await Task.CompletedTask;
}