使用异步等待与WhenAll一次性对象 [英] Using Await Async WhenAll with Disposable Objects
问题描述
我已经打了试图处理(或者不管运行时感觉配合)使用一次性对象时多个并行任务的问题。在下面的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屋!