我正在尝试创建一个在集合上做一些工作的异步控制台应用程序。我有一个使用并行for循环的版本,另一个使用async/await的版本。我期望async/await版本的工作方式与并行版本相似,但它是同步执行的。我做错了什么?
class Program
{
static void Main(string[] args)
{
var worker = new Worker();
worker.ParallelInit();
var t = worker.Init();
t.Wait();
Console.ReadKey();
}
}
public class Worker
{
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5).ToList();
foreach (var i in series)
{
Console.WriteLine("Starting Process {0}", i);
var result = await DoWorkAsync(i);
if (result)
{
Console.WriteLine("Ending Process {0}", i);
}
}
return true;
}
public async Task<bool> DoWorkAsync(int i)
{
Console.WriteLine("working..{0}", i);
await Task.Delay(1000);
return true;
}
public bool ParallelInit()
{
var series = Enumerable.Range(1, 5).ToList();
Parallel.ForEach(series, i =>
{
Console.WriteLine("Starting Process {0}", i);
DoWorkAsync(i);
Console.WriteLine("Ending Process {0}", i);
});
return true;
}
}
发布于 2013-10-18 00:06:04
使用await
关键字的方式告诉C#,您希望在每次通过循环时都等待,这不是并行的。你可以像这样重写你的方法来做你想做的事情,方法是存储一个Task
的列表,然后用Task.WhenAll
对它们进行await
。
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5).ToList();
var tasks = new List<Task<Tuple<int, bool>>>();
foreach (var i in series)
{
Console.WriteLine("Starting Process {0}", i);
tasks.Add(DoWorkAsync(i));
}
foreach (var task in await Task.WhenAll(tasks))
{
if (task.Item2)
{
Console.WriteLine("Ending Process {0}", task.Item1);
}
}
return true;
}
public async Task<Tuple<int, bool>> DoWorkAsync(int i)
{
Console.WriteLine("working..{0}", i);
await Task.Delay(1000);
return Tuple.Create(i, true);
}
发布于 2013-10-17 23:56:13
您的代码将等待每个操作(使用await
)完成,然后再开始下一次迭代。
因此,你得不到任何并行性。
如果您希望并行运行现有的异步操作,则不需要await
;您只需获取Task
的集合,并调用Task.WhenAll()
返回一个等待所有这些操作的任务:
return Task.WhenAll(list.Select(DoWorkAsync));
发布于 2013-10-18 00:05:47
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5);
Task.WhenAll(series.Select(i => DoWorkAsync(i)));
return true;
}
https://stackoverflow.com/questions/19431494
复制相似问题