Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

await in Parallel.foreach [duplicate]

I have an async method which will be used in Parallel.Foreach. in the async method there is await for a Task. However, in the test, seems there are no await behavior, the await Task didn't complete. What's the problem? Below is the code.

public void method1()
{
  Ilist<string> testList = new IList<string>(){"1","2","3"};
  Parallel.ForEach(testList, ()=>
  {
       method2();
  });
}
public async void method2()
{
   await Task.run(()=>{  some other codes here });  
}
like image 826
user1438980 Avatar asked Apr 12 '13 08:04

user1438980


2 Answers

Late to answer, but it looks like you're trying to perform CPU-bound work in parallel, as opposed to performing I/O-bound work asynchronously. Parallel.ForEach is taking care of your parallelism, so no need for Task.Run, and async/await are gaining you nothing here. I'd suggest removing those bits from method2, so the whole thing simplifies to:

public void method1()
{
    Ilist<string> testList = new IList<string>(){"1","2","3"};
    Parallel.ForEach(testList, ()=>
    {
        method2();
    });
}
public void method2()
{
    // some other (plain old synchronous) code here
}
like image 107
Todd Menier Avatar answered Nov 18 '22 22:11

Todd Menier


void async methods are 'fire and forget', and there's no way to wait for them to complete. When method2 is called in your parallel loop, it returns immediately, so your loop is only ensuring the tasks in method2 are created before the loop completes.

You can change the return type of method2 to Task which will allow you to wait on the result of the operation e.g.

public async Task method()
{
     await Task.Run(() { some other code here });
}

which you can wait for in your loop with

method2().Wait();

although doing this is no better than just running the body of the task in method2 directly in your foreach delegate.

like image 42
Lee Avatar answered Nov 18 '22 21:11

Lee