1

I am trying to make part of my system run in parallel, but some some reason do it wait for each element before it starts the next even though i have not told it to await. I would like to start executing ExecuteItem for each this.Items and then continue when they are all done.

bool singleThread = false; public async Task Execute() { if (!this.singleThread) { var tasks = this.Items.Select(x => this.ExecuteItem(x)).ToArray(); Task.WaitAll(tasks); } else { foreach (var item in this.Items) { await this.ExecuteItem(item); } } } private async Task ExecuteItem(IMyItem item) { MappedDiagnosticsContext.Set("itemRef", item.ItemRef); try { await this.HandelItem(item); } catch (Exception exp) { Logger.ErrorException(string.Format("Execution for {0} failed.", item.ItemName), exp); Logger.Error("Error Message: ", exp.Message); } MappedDiagnosticsContext.Remove("itemRef"); } 

To make clear my problem my code behaves as if had wrote the following

var tasks = this.Items.Select(x => await this.ExecuteItem(x)).ToArray(); 

To make sure it was not some kind of linq problem have i rewriten the problem code to the following, however the code still blocks tasks[i] = this.ExecuteItem(this.Items[i]);

 Task[] tasks = new Task[this.Items.Count]; for (int i = 0; i < this.Items.Count; i++) { Console.WriteLine("Adding " + this.Items[i].ItemName); tasks[i] = this.ExecuteItem(this.Items[i]); } Console.WriteLine("Waiting!!!"); Task.WaitAll(tasks); 
3
  • Not really clear what is the problem you have. It looks like code you have should behave exactly as you expect ("start executing ExecuteItem for each this.Items and then continue when they are all done")... Commented May 30, 2015 at 23:31
  • "even though i have not told it to await" but, you have an await for each one. Commented May 30, 2015 at 23:32
  • @JonHanna That is for when i want to run it in a single thread, i have tested the code do not enter there. Commented May 30, 2015 at 23:35

2 Answers 2

3

Something in HandelItem is blocking.

async methods don't run completely asynchronously, they execute synchronously up until the point they hit an await. So all of ExecuteItem, up to HandelItem will run before the tasks list is built. This synchronous behavior would continue into HandelItem if it is an async method, so likely HandelItem is executing while building up the tasks list.

This is easily seen with this example program:

static void Main(string[] args) { var items = Enumerable.Range(1, 2); Console.WriteLine("Start"); var tasks = items.Select(i => AsyncMethod(i)).ToArray(); Console.WriteLine("Got tasks"); Task.WaitAll(tasks); Console.WriteLine("Done!"); } static async Task AsyncMethod(int i) { Console.WriteLine("Enter {0}", i); await AsyncMethod2(i); await Task.Delay(1000); Console.WriteLine("Exit {0}", i); } static async Task AsyncMethod2(int i) { Console.WriteLine("Enter2 {0}", i); await Task.Delay(2000); Console.WriteLine("Exit2 {0}", i); } 

It's output is:

Start Enter 1 Enter2 1 Enter 2 Enter2 2 Got tasks Exit2 2 Exit2 1 Exit 1 Exit 2 Done! 

So both async methods run while building the task list, up until the point that they have to wait. So if HandelItem does something non-asynchronous, it will cause blocking.

Sign up to request clarification or add additional context in comments.

2 Comments

Ok as i see this would be the correct way to solve my problem? private Task ExecuteItem(IElancePropertyScraper scraper) { return Task.Run(async () => {
It could work. It's hard to give concrete recommendations exactly knowing the use case. Although I would probably use Parallel.ForEach to process the loop in parallel
2

If you want the tasks to execute in parallel; and wait until all are complete:

await Task.WhenAll(this.Items.Select(item=>this.ExecuteItem(item))); 

2 Comments

This sadly also waits for each ExecuteItem to finish before the next begins
What then if i had code in ExecuteItem that could first be executed after that HandelItem had finished?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.