I have a code which runs on thread1. I call a function in a synchronic way (using async method but it shouldn't disturb me - async method doesn't turn code to be asynchronic).
I have an await with ConfigureAwait set to false, so I understood the code after it is a task continuation which suppose to run in a different thread than the code before the await (because ConfigureAwait was set to false).
By my test - All code run in the same thread. How is it? Why doesn't the code, below the await, run on a different thread? This is the code:
public async void F1()
{
Console.WriteLine($"Thread.CurrentThread.ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
int x = await F2().ConfigureAwait(false);
Console.WriteLine($"Thread.CurrentThread.ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
}
private async Task<int> F2()
{
Console.WriteLine("Begins F2");
Console.WriteLine($"Thread.CurrentThread.ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine("Finishes F2");
return 7;
}
This is the output:
Thread.CurrentThread.ManagedThreadId=1
Begins F2
Thread.CurrentThread.ManagedThreadId=1
Finishes F2
Thread.CurrentThread.ManagedThreadId=1
I have an await with ConfigureAwait set to false, so I understood the code after it is a task continuation which suppose to run in a different thread than the code before the await (because ConfigureAwait was set to false).
No. There are a couple of misunderstandings here.
The first misunderstanding is regarding what ConfigureAwait(false)
does.
ConfigureAwait
(and await
) have nothing to do with threading directly. By default, await
captures a context - the current SynchronizationContext
or TaskScheduler
. This context could resume on the same thread (e.g., UI SynchronizationContext
s commonly do this), but "context" does not necessarily mean "thread" (e.g., the ASP.NET pre-Core SynchronizationContext
can resume on any thread pool thread).
What ConfigureAwait(false)
actually does is skip capturing that context. So the thread pool context is used, which may run on any thread pool thread. Note that if the code before await
was running on a thread pool thread, it may resume on any thread pool thread, including the thread that it was running on before.
The second misunderstanding is regarding when ConfigureAwait(false)
is applied.
await
will first check to see if its awaitable is complete, and only then will it actually behave asynchronously. So if you await
an already-completed task, the ConfigureAwait(false)
is never even considered - the code just continues running synchronously.
How can I enforce it to run on a different thread then?
Use Task.Run
. Task.Run
is the proper tool to use when you need to run code on a thread pool thread.
It is not "supposed to run in a different thread context", it is allowed to. In the opposite case (ConfigureAwait(true)
) it must continue on the same thread context.
Furthermore when there is nothing to await (inside the method), the "async" method runs synchronously so doesn't need to return to some thread context, it is still on it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With