9

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 });  
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
user1438980
  • 187
  • 1
  • 3
  • 13
  • This is the better worded question for this issue, but a dupe of it has the best answer to it: http://stackoverflow.com/a/11565317/176877 – Chris Moschini Nov 30 '13 at 19:32
  • It isn't though: the code example shows that OP's assumptions about async-await and TPL are flawed from the start, in ways that just confuse the question. – Marc L. Jan 02 '18 at 15:38

2 Answers2

7

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
}
Todd Menier
  • 37,557
  • 17
  • 150
  • 173
2

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.

Lee
  • 142,018
  • 20
  • 234
  • 287
  • Yes, you are right, it works. The reason I have to run in method2 because I have to pass different Func to the method1. like create, delete, etc. thanks a lot . – user1438980 Apr 14 '13 at 03:59