使用异步等待与WhenAll一次性对象 [英] Using Await Async WhenAll with Disposable Objects

查看:108
本文介绍了使用异步等待与WhenAll一次性对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经打了试图处理(或者不管运行时感觉配合)使用一次性对象时多个并行任务的问题。在下面的code段,每个处理器对象立即处置之前,已经做了所需要的工作。

I've hit a problem trying to process multiple Tasks in parallel (or however the runtime feels fit) when using disposable objects. In the following code snippet, each Processor object is immediately disposed BEFORE it has done the required work.

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);
}

重新写code如下结果在各处理器执行其处理,然后被设置,但它不是以运行不依赖于彼此的多个任务的最有效方式。

Re-writing the code as below results in the each Processor performing its processing and THEN being disposed, but it's not the most efficient way to run multiple Tasks that don't depend on one another.

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();
        }
    }
}

有人请解释为什么第一个例子是处置早,并给出这种情况下的最佳code模式的一个例子。

Can someone please explain why the first example is disposing 'early' and give an example of the best code pattern for this situation.

推荐答案

它有助于觉得等待作为暂停当前的方法的,甚至虽然它不会阻止的线程

It helps to think of await as pausing the current method, even though it doesn't block the thread.

在你的第一个例子,当你执行的foreach 循环,每次你创建一个处理器,开始操作(保存操作的任务在列表中),然后处置处理器。你的的foreach 循环结束后,那么你(异步)等待所有操作完成。

In your first example, when you are executing the foreach loop, each time you create a Processor, start an operation (saving the operation's Task in a list), and then dispose the Processor. After your foreach loop is finished, then you (asynchronously) wait for all the operations to complete.

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

In your second example, when you are executing the foreach loop, each time you create a Processor, start an operation, (asynchronously) wait for it to complete, and then dispose the Processor.

要解决这个问题,你应该写一个辅助方法,因为这样的:

To fix this, you should write a helper method, as such:

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

您的辅助方法定义了一个更高级别的操作,这将在适当的时间处理自己的处理器资源的照顾。然后你就可以同时启动所有工作这样:

Your helper method defines a higher-level operation, which will take care of disposing its own Processor resource at the appropriate time. Then you can start all your work concurrently as such:

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

这篇关于使用异步等待与WhenAll一次性对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆