zoukankan      html  css  js  c++  java
  • 如何在循环中使用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

  • 相关阅读:
    3、面向对象
    今日记事
    javascript 学习javascript高级程序设计
    数据库操作语言分类
    project遇到问题了。
    CentOS设置程序开机自启动的方法
    ECMAScript 基础 [完]
    CentOS 网络设置修改
    Spring Boot项目Circular view path问题解决
    数据库设计
  • 原文地址:https://www.cnblogs.com/yanglang/p/9602165.html
Copyright © 2011-2022 走看看