0
votes

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
2
Your code is not actually async. Try at least add await Task.Delay(...) or Task.Yield to F2Guru Stron
Aside to the question, async void is an anti-pattern and should not be used in most cases: markheath.net/post/async-antipatternsMartin Costello

2 Answers

5
votes

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.

3
votes

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 SynchronizationContexts 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.