c# - 对一次性对象使用 Await Async WhenAll

标签 c# design-patterns async-await idisposable

在使用一次性对象时,我在尝试并行处理多个任务(或者运行时感觉合适)时遇到了问题。在以下代码片段中,每个 Processor 对象在完成所需工作之前立即被释放。

async public Task ProcessData(IEnumerable<int> data)
{
    var tasks = new List<Task>();

    foreach (var d in data)
    {
        using (var processor = new Processor(d))
        {
            processor.Completed += (sender, e) => { // Do something else };
            tasks.Add(processor.ProcessAsync());
        }
    }

    await Task.WhenAll(tasks);
}

如下重写代码会导致每个处理器执行其处理然后被处置,但这不是运行多个不依赖于彼此的任务的最有效方式。

async public Task ProcessData(IEnumerable<int> data)
{
    foreach (var d in data)
    {
        using (var processor = new Processor(d))
        {
            processor.Completed += (sender, e) => { // Do something else };
            await processor.ProcessAsync();
        }
    }
}

有人可以解释一下为什么第一个示例“提前”处理并给出了针对这种情况的最佳代码模式的示例。

最佳答案

这有助于将 await 视为暂停当前的方法,即使它不会阻塞线程

在你的第一个例子中,当你执行 foreach 循环时,每次你创建一个 Processor 时,开始一个操作(保存操作的 Task 在列表中),然后处理 Processorforeach 循环完成后,您(异步地)等待所有操作完成。

在你的第二个例子中,当你执行 foreach 循环时,每次你创建一个 Processor ,开始一个操作,(异步)等待它完成,然后处理 Processor

要解决这个问题,您应该编写一个辅助方法,如下所示:

private static async Task ProcessData(int data)
{
  using (var processor = new Processor(d))
  {
    processor.Completed += (sender, e) => { /* Do something else */ };
    await processor.ProcessAsync();
  }
}

您的辅助方法定义了一个更高级别的操作,它将负责在适当的时候处理自己的 Processor 资源。然后你就可以同时开始所有的工作了:

public async Task ProcessData(IEnumerable<int> data)
{
  ...
  await Task.WhenAll(data.Select(d => ProcessData(d)));
  ...
}

关于c# - 对一次性对象使用 Await Async WhenAll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17797036/

相关文章:

java - 我应该使用哪种工厂设计模式?

java - 浏览器在页面重新加载时要求重新发送数据

c# - 在 .NET 4.0 中使用 task.run 与 task.run 和 continuewith 进行异步/等待

javascript - React 的 API 响应为空

c# - 任务栏右键单击应用程序上下文菜单[JumpList]

c# - C# 中从字符串中删除换行符的最简单方法是什么?

c# - 在规范中组合 C# 代码和数据库代码

c# - IMAPI界面可以选择刻录模式吗?

javascript - 管理 View 文件和 JS 标记

node.js - Node 等待 Promise.all() 完全解决