如何在循环中使用await
我试图创build一个asynchronous控制台应用程序,在集合上做了一些工作。 我有一个版本使用并行循环另一个版本,使用asynchronous/等待。 我期望asynchronous/等待版本工作类似于并行版本,但它同步执行。 我究竟做错了什么?
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; } }
您使用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); }
在开始下一次迭代之前,您的代码会等待每个操作(使用await
)完成。
所以你没有任何并行性。
如果要并行运行现有的asynchronous操作,则不需要await
; 你只需要得到一个Task
的集合,并调用Task.WhenAll()
来返回一个等待它们的任务:
return Task.WhenAll(list.Select(DoWorkAsync));
public async Task<bool> Init() { var series = Enumerable.Range(1, 5); Task.WhenAll(series.Select(i => DoWorkAsync(i))); return true; }