vmb
vmb

Reputation: 3028

Issue with calling async method inside Parallel.Foreach method

I have case there i want to call one asyn method inside paralle.Foreach loop

    public void ItemCheck<T>(IList<T> items,int id)
          {       
              Parallel.ForEach(items, (current) =>
            {
                PostData(current,id);
            });
            Console.log("ItemCheck executed")
     }
     public async void PostData<T>(T obj, int id)
      {
        Console.lgo("PosstData executed")
      }

Output :

ItemCheck executed 
PosstData executed

Why it happens like this ?? Before completing execution of PostData method,next line is executed.How can i solve this issue.Anyone help on this

Upvotes: 1

Views: 1273

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 457382

Why it happens like this ??

Because you're using async void.

Also - as Jon Skeet mentioned - there's no point in doing parallelism here. Parallel processing is splitting the work over multiple threads. What you really want is concurrency, not parallelism, which can be done with Task.WhenAll:

public async Task ItemCheckAsync<T>(IList<T> items, int id)
{
  var tasks = items.Select(current => PostDataAsync(current, id));
  await Task.WhenAll(tasks);
}
public async Task PostDataAsync<T>(T obj, int id)

The phrase "in parallel" is commonly used to mean "doing more than one thing at a time", but that usage has misled you into using Parallel, which is not the appropriate tool in this case. This is one reason why I strongly prefer the term "concurrent", and reserve the term "parallel" for things that the Parallel class does.

Upvotes: 3

vasil oreshenski
vasil oreshenski

Reputation: 2836

The problem is that your PostData method is executed asynchronous and nothing tells the parallel loop to wait until completion of all task. An alternative i would use to sync the execution flow:

var tasks = items
.AsParallel()
.WithDegreeOfParallelisum(...)
.Select(async item => await PostData(item, id))
.ToArray();

Task.WaitAll(tasks);  // this will wait for all tasks to finnish

Also your async methods, even void they should return Task not void. Being more explicit about your code is one plus of this approach, additionally, you can use the task for any other operations, like in the case be waited to finish.

 public async Task PostData<T>(T obj, int id)

Do you even need to create/start async task in parallel and then wait for them? The result of this is just creating tasks in parallel (which is not a heavy operation, so why do it in parallel ?). If you dont do any additional heavy work in the parallel loop except the PostData method, i think you don't need the parallel loop at all.

Upvotes: 0

Related Questions