JKennedy
JKennedy

Reputation: 18799

Correct use of ConfigureAwait(false) when chaining tasks

So I have a method that chains tasks together to do work

var tasks = new List<Task>();

tasks.Add(DoWorkAsync(1));
tasks.Add(DoWorkAsync(2));
tasks.Add(DoWorkAsync(3));
tasks.Add(DoWorkAsync(4));
tasks.Add(DoWorkAsync(5));
tasks.Add(DoWorkAsync(6));

await Task.WhenAll(tasks.ToArray());

To get better performance/responsiveness out of this method I was looking at using ConfigureAwait(false)

The above method does not have any need to run on the same synchronisation context as the calling thread.

what is the correct way to use ConfigueAwait(false) when chaining Tasks and do I need to use ConfigureAwait for each individual task and/or do i need to use it on Task.WhenAll

As an extra question...

Does ConfigureAwait actually do anything (or improve performance/responsiveness) if there is no code that runs after the await?

Upvotes: 2

Views: 1073

Answers (1)

JKennedy
JKennedy

Reputation: 18799

Ok so from the comments and chaining a few other questions together I think I have a better understanding of when to use configure await...

All of the below suggestions presume your task does not need to return to the calling thread. i.e. you have a valid ConfigureAwait use case

  1. ConfigureAwait configures the await, not the Task - You only need to use ConfigureAwait on the line where await is used

    From this answer: Using ConfigureAwait(false) on tasks passed in to Task.WhenAll() fails

  2. You do need to use ConfigureAwait even if it is the last line in the method

    From This answer: Does Task.ConfigureAwait(false) on the last method line affect anything?

  3. ConfigureAwait doesn't need to be called when using ContinueWith

    From this answer: ConfigureAwait(false) when using ContinueWith

  4. Tasks contained in Task.WhenAll are already configured with ConfigureAwait

    Also from this answer: Using ConfigureAwait(false) on tasks passed in to Task.WhenAll() fails

Which leaves me with my code looking like so:

var tasks = new List<Task>();

tasks.Add(DoWorkAsync(1));
tasks.Add(DoWorkAsync(2));
tasks.Add(DoWorkAsync(3));
tasks.Add(DoWorkAsync(4));
tasks.Add(DoWorkAsync(5));
tasks.Add(DoWorkAsync(6));

await Task.WhenAll(tasks.ToArray()).ConfigureAwait(false);

To my surprise it seems that using ConfigureAwait is advised by most of the community, although when talking about Threading/async/await this never really gets a mention.

Extra information: Why would I bother to use Task.ConfigureAwait(continueOnCapturedContext: false);

I'm not an expert in this field I've just linked together relevent other questions, so if I've missed anything / got anything wrong, feel free to chip in.

Upvotes: 4

Related Questions