Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConfigureAwait(false) - Does the continuation always run on different thread?

This question is asked in the context of ASP.NET WebApi 2 (not ASP.NET Core). I have tried to do my own research on this topic, however I could not find the explicit answer to this.

The official MSDN documentation for the ConfigureAwait(...) method parameter states following:

true to attempt to marshal the continuation back to the original context captured; otherwise, false.

Stephen Toub further explains the attempt keyword as follows:

That means there may not be anything to marshal back to... there may not be a context to capture, e.g. SynchronizationContext.Current may return null.

If I understand it correctly, then this is not the case for the ASP.NET WebApi 2, because there is AspNetSynchronizationContext present, right?

Now lets take a look at following controller action method:

[HttpGet]
public async Task<String> GetValues()
{
    // First half.

    var values = await HeavyIo().ConfigureAwait(false);

    // Second half.

    return values;
}

By passing continueOnCapturedContext: false is it guaranteed that that the continuation labeled as // Second half. gets always executed on different thread? Or is there chance that if the thread on which the synchronization context got captured will be free when async operation completes, then the continuation will run on that same thread?

like image 834
Markkknk Avatar asked Nov 24 '18 09:11

Markkknk


1 Answers

When asked in the negative form like that the answer is, i think, pretty clear - there is no guarantee that the second half will be executed on a different thread to the first half. As you speculate, the original thread might well be the lucky next-to-be-picked available thread, when the continuation is up for executing.

Also important to note is that it's the context, not necessarily the thread, that is restored. In the case of a Windows message loop (e.g. WinForms UI thread), it is the UI thread running the message loop that picks up and executes the continuation, hence with ConfigureAwait(true), the same thread is guaranteed. With other SynchronizationContexts, though, there might be no particular reason to require or even prefer the original thread, as long as whatever is considered by them to be "context" is restored; e.g. HttpContext.Current [, identity, culture] in ASP.NET.

There is also an at-least theoretical chance that HeavyIo() completes synchronously, in which case there is no context-switching anyway, and the second half will simply continue on the same thread as the first. I can only assume from your choice of naming ("heavy") that you're implying this won't be an option.

like image 148
sellotape Avatar answered Oct 22 '22 20:10

sellotape