【问题标题】:Threading foreach that abides by async/await methods inside said foreach在所述 foreach 中遵循 async/await 方法的线程化 foreach
【发布时间】:2017-05-20 13:30:02
【问题描述】:

我一直在寻找一种方法来遍历具有多个线程的 foreach,例如,假设我有一个列表

public List<MYclass> All()
{
     // fill the list
}


Private async Task Main()
{
     foreach(All() as whatever)
    {
        await method();
        await method2();
    }
}

private async Task method()
{
     //do some stuff
     // more stuff
     await another();
}


private async Task method2()
{
     //do some stuff
     // more stuff
     await another2();
}

private async Task another()
{
     //await client to do whatever
}

private async Task another2()
{
     //await client to do whatever
}

我正在尝试执行以下操作:

列表项 1 = thread1

列表项 2 = thread2

列表项 3 = thread3

...等取决于我有多少线程

我一直在四处寻找,没有希望,我找到了 Parrellel.foreach,但这不会等待等待,因为一旦它到达等待,它就会完成整个动作然后再次启动 foreach,所以我怎么能去实现我想要的?任何帮助将不胜感激。

【问题讨论】:

  • 在所有方法都完成工作后,您要继续处理All 中的下一项吗?
  • 而不是await method();,为什么不tasks.Add(method());等然后调用await Task.WhenAll(tasks);

标签: c#


【解决方案1】:

首先要说的是,async/await 代码并不是真正的 multi threaded 。我认为它有时会创建另一个线程,但它主要是为了缓解代码中的阻塞。

我倾向于认为混合多线程和异步实际上有点痛苦,因为异常处理有点困难且难以预测。您最好使用 Parallel foreach,并从方法调用定义中移除异步。或者只是在并行 foreach 中调用 .Result 以使该代码同步执行。

【讨论】:

    【解决方案2】:

    “线程”这个概念现在太低级了——毕竟,当一个方法是awaiting 时,它甚至不使用线程。相反,您应该考虑“任务”和“操作”。

    在这种情况下,您想要的是异步并发(不是并行/线程并发)。首先,定义您希望对每个项目执行的(单个)操作:

    private async Task ProcessAsync(MyClass item)
    {
      await method();
      await method2();
    }
    

    接下来,要同时启动所有任务的操作,您可以使用Select

    private async Task Main()
    {
      var tasks = All().Select(ProcessAsync).ToArray();
    }
    

    然后,要(异步)等待它们全部完成,请使用await Task.WhenAll

    private async Task Main()
    {
      var tasks = All().Select(ProcessAsync).ToArray();
      await Task.WhenAll(tasks);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 2021-06-20
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 2022-06-23
      相关资源
      最近更新 更多