如何在循環中使用await?


我正在嘗試創建一個異步控制台應用程序,對集合進行一些操作。我有一個版本使用並行for循環,使用異步/等待。我預計異步/等待版本的工作類似於並行版本,但它同步執行。是什么原因呢?

 1 class Program
 2 {
 3     static void Main(string[] args)
 4     {
 5         var worker = new Worker();
 6         worker.ParallelInit();
 7         var t = worker.Init();
 8         t.Wait();
 9         Console.ReadKey();
10     }
11 }
12 
13 public class Worker
14 {
15     public async Task<bool> Init()
16     {
17         var series = Enumerable.Range(1, 5).ToList();
18         foreach (var i in series)
19         {
20             Console.WriteLine("Starting Process {0}", i);
21             var result = await DoWorkAsync(i);
22             if (result)
23             {
24                 Console.WriteLine("Ending Process {0}", i);
25             }
26         }
27 
28         return true;
29     }
30 
31     public async Task<bool> DoWorkAsync(int i)
32     {
33         Console.WriteLine("working..{0}", i);
34         await Task.Delay(1000);
35         return true;
36     }
37 
38     public bool ParallelInit()
39     {
40         var series = Enumerable.Range(1, 5).ToList();
41         Parallel.ForEach(series, i =>
42         {
43             Console.WriteLine("Starting Process {0}", i);
44             DoWorkAsync(i);
45             Console.WriteLine("Ending Process {0}", i);
46         });
47         return true;
48     }
49 }

使用await關鍵字的方式告訴C#,你希望每次通過循環時都等待,而循環並不平行。你可以像這樣重寫你的方法來做你想做的事情,通過存儲Tasks 的列表然后將await它們全部加入Task.WhenAll

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在開始下一次迭代之前,你的代碼會等待每個操作(使用)完成。 因此,你沒有任何並行性。

如果你想並行運行一個現有的異步操作,你不需要await; 你只需要得到一個Tasks 的集合並且調用Task.WhenAll()返回一個等待它們的任務:

return Task.WhenAll(list.Select(DoWorkAsync));

 代碼:

https://github.com/kuaidaoyanglang/TaskTest


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM