Thought I was getting a handle on ConfigureAwait
, then I tried an experiment.
My understanding is that ConfigureAwait(false)
will only make a difference if there is a synchronization context.
ASP, WPF, etc. should have a context, but console apps and service apps should not.
To see how it works I made a Web API app and included the following method:
// GET api/values/5
public async Task<string> Get (int id)
{
var syncCtx = SynchronizationContext.Current;
int startThreadId = Thread.CurrentThread.ManagedThreadId;
await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(true);
int endThreadId = Thread.CurrentThread.ManagedThreadId;
return "Start Thread ID: " + startThreadId.ToString() +
": End Thread ID: " + endThreadId.ToString();
}
My prediction was that with no ConfigureAwait
or ConfigureAwait
set to true
, I should see the same thread ID before and after the await.
My first few tests showed exactly that with the true set as above.
Later runs of the code started and ended on different thread ids regardless of ConfigureAwait
.
I added syncCtx
to convince myself I have a context.
The one caveat I have read is that if the task has completed, you won't be guaranteed the same ID. Is that the case here? If so, why is that the case?
Have I set up a naive or flawed test? If so, what would be a proper test?
I started down this path in a console/service app and realized I was not getting the same thread ID. I was adding ConfigureAwait(false)
as recommended in most "best practice" write ups I have seen. Since I like to see how things really work, I tried testing the Thread IDs. Seeing them differ led me through a number of searches that resulted in the above code.
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.
Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.
Originally Answered: What is the full form of C ? C - Compiler . C is a general-purpose, high-level language that was originally developed by Dennis M. Ritchie to develop the UNIX operating system at Bell Labs. C was originally first implemented on the DEC PDP-11 computer in 1972.
Doing ConfigureAwait(true)
(or just leaving it off, as it is the default value) does not make it run on the same thread. It tells SynchronizationContext.Current
to do a Post
or Send
with the rest of the continueation. How Post or Send actually runs that code is not defined.
WindowsFormsSynchronizationContext
and DispatcherSynchronizationContext
(WinForms and WPF's contexts) both will put the continuation on to the queue of messages to be processed by the Message Pump (the UI thread).
On the other hand, AspNetSynchronizationContext
(which is what you are running under) just sets some state information up (like setting HttpContext.Current
back to its old value), it then queues the work on the next available thread pool thread. There is no "Message Pump" for ASP.NET, it just does all of its work on the thread pool, so there is no point in trying to get the same thread out of the thread pool at a later time, that thread may already been destroyed by the time the continuation happens.
The times you saw the same ID before and after you just got lucky and the same thread got pulled out of the thread pool before and after the continuation.
I highly recommend you read the MSDN magazine article "It's All About the SynchronizationContext", it goes in to detail explaining how the SynchronizationContext works and goes in to a little detail about the 4 types of contexts built in to .NET.
SynchronizationContext
!= Thread
. If you were using something like WPF with its Dispatcher
runtime then, yes, its SynchronizationContext
happens to be tied to one specific thread. However things like ASP.NET and WCF are not thread affine, they just carry along with them specific ambient context that needs to be restored on whatever thread they begin executing on next. They may be affine to a specific thread pool, but, again, not a specific thread.
This is precisely why the SynchronizationContext
abstraction was introduced: it allows different frameworks to decide exactly what affinity means to them and allows the async/await infrastructure to work on top of them in a totally agnostic way.
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