async Task() not returning straight away when not using await

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


async Task<T>() not returning straight away when not using await



If I have the following function


public async Task<bool> Foo()
{
// call many async functions
await Bar1().ConfigureAwait(false);
await Bar2().ConfigureAwait(false);
return await Bar3().ConfigureAwait(false);
}



If I call the function above


var t1 = Foo();
var t2 = Foo();
...
await Task.WhenAll(t1, t2).ConfigureAwait(false);



t2 will not execute until t1 completes, (so calling WaitAll is a bit pointless).


WaitAll



But if I call


...
var t1 = Task.Run( async () => await Foo().ConfigureAwait(false));
var t2 = Task.Run( async () => await Foo().ConfigureAwait(false));
...
await Task.WhenAll(t1, t2).ConfigureAwait(false);



t1 and t2 return immediately...



And now if I run ...


...
var t1 = Task.Run( () => Foo());
var t2 = Task.Run( () => Foo());
...
await Task.WhenAll(t1, t2).ConfigureAwait(false);



t1 and t2 also return immediately...



Why does Foo() not return task immediately?



And, should I call Task.Run( () => Foo()) or Task.Run( async () => await Foo().ConfigureAwait(false))


Task.Run( () => Foo())


Task.Run( async () => await Foo().ConfigureAwait(false))





how are you verifying those results? do you print to stdout or?
– smn.tino
12 mins ago





Yes, I print to console when t1 start/complete, t2 start/completes and when WaitAll starts/complete. Those are long running functions, so there is no way that t1 complete before t2 starts
– Simon Goodman
9 mins ago


t1


t2


WaitAll


t1


t2





"t2 will not execute until t1 completes" -- t2 should execute as soon as t1 is first interrupted. If it is never interrupted, that suggests you don't actually have any async code in Bar1/Bar2/Bar3. Is that correct?
– hvd
6 mins ago


Bar1


Bar2


Bar3





Hum, no, I have a few async code inside that function, (between 3 and 5). Those are database calls (Sqlite .NET).
– Simon Goodman
16 secs ago




1 Answer
1



Since ConfigureAwait(false) "fixes" the problem, the issue is readily apparent. You're starting off in a single-threaded context (e.g. a UI thread). This means that all of the code that runs between your await calls has to run on that one single thread. Which means that although you do start multiple tasks, they're unable to make progress in parallel.


ConfigureAwait(false)


await



Whether the code within Bar1, Bar2, etc is able to make progress in parallel across multiple calls is an implementation detail of those methods, so I cannot answer whether they're also bound to the same single thread.


Bar1


Bar2



Bear in mind, await doesn't start anything. You hand it a Task (or other awaitable) and it does, literally, just wait for it to finish (whilst not tying up whatever thread was running this method at the point we hit an await). How that Task will be completed, how it was started, etc, are all details irrelevant to await.


await


Task


await


Task


await





The OP hasn't said ConfigureAwait(false) by itself fixes the problem, as far as I can tell. ConfigureAwait(false) is only used combined with Task.Run in the question. My guess was it was simply a long-running CPU-bound function, and it was Task.Run that fixed it. (Edit: someone else edited the question to turn the erroneous ConfigureAwait() into ConfigureAwait(false). If that is what the OP meant, then ConfigureAwait(false) didn't "fix" anything.)
– hvd
2 mins ago




ConfigureAwait(false)


ConfigureAwait(false)


Task.Run


Task.Run


ConfigureAwait()


ConfigureAwait(false)


ConfigureAwait(false)






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Visual Studio Code: How to configure includePath for better IntelliSense results

Spring cloud config client Could not locate PropertySource

Regex - How to capture all iterations of a repeating pattern?