• 如何在循环中使用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

  • 相关阅读:
    AcWing 1027. 方格取数 dp
    AcWing 1014. 登山 dp
    acwing 482. 合唱队形 dp
    LeetCode 1463. 摘樱桃II dp
    LeetCode 100. 相同的树 树的遍历
    LeetCode 336. 回文对 哈希
    LeetCode 815. 公交路线 最短路 哈希
    算法问题实战策略 DARPA大挑战 二分
    算法问题实战策略 LUNCHBOX 贪心
    AcWing 1100. 抓住那头牛 BFS
  • 原文地址:https://www.cnblogs.com/yanglang/p/9602165.html
Copyright © 2020-2023  润新知