如何从一个循环内,不必等待调用异步方法? [英] How to call an async method from within a loop without awaiting?
问题描述
考虑这块code的,其中有一些正在工作中的一个做了循环,然后递归调用来处理子项目。我想转换DoSomething的(项目),并GetItems(ID),以异步方法,但如果我在等待着他们这里,for循环是要等待每次迭代移动的,基本上失去了并行处理的好处之前完成。我怎么能改善这个方法的性能?是否有可能使用异步办呢/等待?
公共无效的DoWork(字符串ID)
{
变种项= GetItems(ID); //需要时间 如果(项目== NULL)
返回; Parallel.ForEach(项目,项目= GT;
{
DoSomething的(项目); //需要时间
DoWork的(item.subItemId);
});
}
Parallel.ForEach
遍历所有的项目,您可以创建一个任务序列,然后使用 Task.WhenAll
等待他们全部完成。当你的code还涉及递归它变得稍微复杂一点,你需要结合的DoSomething
和的DoWork
成单一的方法我已经恰当地命名为 DOIT
:
异步任务的DoWork(字符串ID){
变种项= GetItems(ID);
如果(项目== NULL)
返回;
VAR任务= items.Select(DOIT);
等待Task.WhenAll(任务);
}异步任务DOIT(项目项目){
等待DoSomething的(项目);
等待的DoWork(item.subItemId);
}
混合 Parallel.ForEach
和异步/等待是一个坏主意。 Parallel.ForEach
将让你的code并行和计算密集型并行的,但是你的算法获得最佳性能运行。但是异步/的await让您的code并发执行和被阻塞在IO操作该实例重用线程。
简体 Parallel.ForEach
将设置尽可能多的线程,你有你的电脑上的CPU内核,然后分区你迭代在这些线程执行的项目。因此, Parallel.ForEach
应一次在你调用堆栈的底部在那里它就会散开工作,多个线程,并等待它们完成使用。里面每个线程的递归的方式调用 Parallel.ForEach
仅仅是疯了,根本不会提高性能。
Consider this piece of code, where there is some work being done within a for loop, and then a recursive call to process sub items. I wanted to convert DoSomething(item) and GetItems(id) to async methods, but if I await on them here, the for loop is going to wait for each iteration to finish before moving on, essentially losing the benefit of parallel processing. How could I improve the performance of this method? Is it possible to do it using async/await?
public void DoWork(string id)
{
var items = GetItems(id); //takes time
if (items == null)
return;
Parallel.ForEach(items, item =>
{
DoSomething(item); //takes time
DoWork(item.subItemId);
});
}
Instead of using Parallel.ForEach
to loop over the items you can create a sequence of tasks and then use Task.WhenAll
to wait for them all to complete. As your code also involves recursion it gets slightly more complicated and you need to combine DoSomething
and DoWork
into a single method which I have aptly named DoIt
:
async Task DoWork(String id) {
var items = GetItems(id);
if (items == null)
return;
var tasks = items.Select(DoIt);
await Task.WhenAll(tasks);
}
async Task DoIt(Item item) {
await DoSomething(item);
await DoWork(item.subItemId);
}
Mixing Parallel.ForEach
and async/await is a bad idea. Parallel.ForEach
will allow your code to execute in parallel and for compute intensive but parallelizable algorithms you get the best performance. However async/await allows your code to execute concurrently and for instance reuse threads that are blocked on IO operations.
Simplified Parallel.ForEach
will setup as many threads as you have CPU cores on your computer and then partition the items you are iterating to be executed across these threads. So Parallel.ForEach
should be used once at the bottom of your call stack where it will then fan out the work to multiple threads and wait for them to complete. Calling Parallel.ForEach
in a recursive manner inside each of these threads is just crazy and will not improve performance at all.
这篇关于如何从一个循环内,不必等待调用异步方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!