1

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

asked Feb 17, 2017 at 11:53
5
  • 6
    I suspect that isn't your actual code. Please post a minimal reproducible example. But fundamentally, your async method is void, which makes it hard to wait for all the tasks to complete before continuing. Additionally, using Parallel.ForEach seems pointless when you're using async methods - just call all the async methods, then wait for all the tasks to complete (when you've changed your async method to return Task) Commented Feb 17, 2017 at 11:55
  • @Jon Skeet .. Inside PostData method,i am calling another method which is for making restcalls.. Commented Feb 17, 2017 at 11:57
  • You don't await your PostData call so your parallel.foreach will complete immediately. It will not wait for PostData to complete. Commented Feb 17, 2017 at 12:03
  • 2
    Indeed, so your sample code isn't representative of your actual code, because (typos aside) you're logging before doing anything. That's why I asked for a minimal reproducible example. Use Task.Delay to emulate actual work. Commented Feb 17, 2017 at 12:20
  • Before completing execution of PostData , that is exactly asynchronous, you cannot and should not use async in Parallel.ForEach which is designed only for synchronous methods. Commented Feb 17, 2017 at 13:02

2 Answers 2

3

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.

answered Feb 17, 2017 at 20:55

Comments

0

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.

answered Feb 17, 2017 at 12:19

8 Comments

Okay.. I will try.. One more thing i need to point out that PostData itself calling another async method
Currently signature of PostMethod is void.. Can i need to change that??
yep, try with Task instead of void, this should be the only change required.
I am new to thjs async concept.. In this case if it will work just by changing return type as Task<int> and simply return 1,from PostMethod.. Bcoz in my case i don't have anything to return from PostMethod and just need to indicate that task is completed
For void methods which are async (in your case) you dont need to return anything from the method when the return type is changed to Task. This just indicates that the method is asynchronous and does not return anything ;]
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.