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?
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
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
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?
ConfigureAwait
doesn't need to be called when using ContinueWith
From this answer: ConfigureAwait(false) when using ContinueWith
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.
I would phrase (1) as "
ConfigureAwait
configures theawait
, not theTask
". IgnoreContinueWith
; it's a low-level, dangerous operation that should almost never be used in modern code.Thanks @StephenCleary. I'm interrested in finding out more about avoiding
ContinueWith
. Have you got any links with information about the problems with it/ avoiding it / alternatives / any valid use casesThe best alternative for
ContinueWith
isawait
. To use properly, you always have to pass aTaskScheduler
. Finally, it's just plain awkward to pass a delegate continuation rather than just continuing theasync
method.