【发布时间】:2023-03-02 22:43:01
【问题描述】:
我有一个带有async Task<Result> 方法的程序,而不是我需要从一个循环中并行运行。
这是我尝试过的两种方法,第一种(ResolveWidgetsTaskFactoryAsync)按预期工作,但另一种(ResolveWidgetsNotParallelAsync)同步运行,即使每个方法都作为任务返回。
在保持异步 Task<string> 返回类型为 ComputeAsync 的同时,我怎样才能更好地编写并行版本?
void Main()
{
var results = ResolveWidgetsTaskFactoryAsync().Result;
results.Dump();
results = ResolveWidgetsNotParallelAsync().Result;
results.Dump();
}
/// <summary>
/// Runs synchronously instead of in parallel
/// /summary>
private async Task<IEnumerable<string>> ResolveWidgetsNotParallelAsync()
{
var values = new[] { "a", "b", "c" };
var widgets = new List<Task<string>>();
foreach (var value in values)
{
Console.WriteLine("Iteration value : " + value);
var widgetTask = ComputeAsync(value);
widgets.Add(widgetTask);
}
return await Task.WhenAll(widgets);
}
/// <summary>
/// Runs as expected, but I'm not sure it's well written
/// /summary>
private async Task<IEnumerable<string>> ResolveWidgetsTaskFactoryAsync()
{
var values = new[] { "a", "b", "c" };
var widgets = new List<Task<string>>();
foreach (var value in values)
{
Console.WriteLine("Iteration value : " + value);
widgets.Add(Task<string>.Factory.StartNew(() => ComputeAsync(value).Result));
}
return await Task.WhenAll(widgets);
}
public async Task<string> ComputeAsync(string value)
{
try
{
Console.WriteLine("Processing value : " + value);
Random rnd = new Random();
var wait = rnd.Next(1000, 5000);
Console.WriteLine("Wait : " + wait);
Thread.Sleep(wait);
return await Task.FromResult(value + " done");
}
catch (Exception e)
{
return null;
}
}
【问题讨论】:
-
因为
ComputeAsync中没有任何异步 -
将
Thread.Sleep(wait);替换为await Task.Delay(wait);,然后重试。 -
不要将
Task<T>与Thread.Sleep(wait);混用,这一行也没有异步widgets.Add(Task<string>.Factory.StartNew(() => ComputeAsync(value).Result));Result阻塞调用 -
Task<string>.Factory.StartNew(() => ComputeAsync(value).Result)这在很多方面都很糟糕。为什么要为已经基于任务的方法调用Factory.StartNew?你为什么要使用阻塞调用.Result?你应该这样做widgets.Add(ComputeAsync(value));并摆脱Thread.Sleep以支持Task.Delay -
请注意,parallel 和 async 是两个完全不同的概念。两者都不暗示对方。
标签: c# async-await task task-parallel-library