My question as the title suggest is about the background of 'async' and 'await'.
Is it true to say that what the current thread reaches 'await' keyword, it goes to "sleep",
and wakes up when the await method is done?
Thanks!
Guy
Is it true to say that what the current thread reaches 'await' keyword, it goes to "sleep", and wakes up when the await method is done?
No. The whole point of async is to avoid having threads sleeping when they could be doing other work. Additionally, if the thread running the async method is a UI thread, you really don't want it to be sleeping at all - you want it to be available to other events.
When execution reaches an await expression, the generated code will check whether the thing you're awaiting is already available. If it is, you can use it and keep going. Otherwise, it will add a continuation to the "awaitable" part, and return immediately.
The continuation makes sure that the rest of the async method gets run when the awaitable value is ready. Which thread that happens in depends on the context in which you're awaiting - if the async method is running in thread pool threads, the continuation could run on a different thread to the one the method started on... but that shouldn't matter. (The rest of the context will still be propagated.)
Note that it's fine for the async method to return without having completed - because an async method can't return a value directly - it always returns a Task<T> (or Task, or void)... and the task returned by the method will be only be completed when the async method has really reached the end.
async is only syntactic sugar that allows await keyword to be used.
If async, await is used in ASP.NET Core, then your request thread will be released to thread pool.
As Stephen Cleary says:
Asynchronous request handlers operate differently. When a request
comes in, ASP.NET takes one of its thread pool threads and assigns it
to that request. This time the request handler will call that external
resource asynchronously. This returns the request thread to the thread
pool until the call to the external resource returns. Figure 3
illustrates the thread pool with two threads while the request is
asynchronously waiting for the external resource.
The important difference is that the request thread has been returned
to the thread pool while the asynchronous call is in progress. While
the thread is in the thread pool, it’s no longer associated with that
request. This time, when the external resource call returns, ASP.NET
takes one of its thread pool threads and reassigns it to that request.
That thread continues processing the request. When the request is
completed, that thread is again returned to the thread pool. Note that
with synchronous handlers, the same thread is used for the lifetime of
the request; with asynchronous handlers, in contrast, different
threads may be assigned to the same request (at different times).
For desktop application:
await releases the current thread, but NOT to the thread pool.
The UI thread doesn't come from the thread pool. If you run asynchronous method,
e.g. ExecuteScalarAsync without async, await keywords, then this method
will run asynchronously no matter what. The calling thread won't be
affected .
Special thanks for nice comments to Panagiotis Kanavos.
E.g. you have a heavy stored procedure and your stored procedure takes 10 minutes to be executed. And if you run this code from C# without async, await keywords, then your execution thread will wait your stored procedure for 10 minutes. And this waiting thread will do nothing, it will just wait stored procedure.
However, if async, await keyword is used, then your thread will not wait stored procedure. The thread will be eligible to work.
Although this question has already been answered by Jon Skeet who is a highly skilled person (and one of my favorites), it is worth reading the contents that I mention below for other readers of this post.
By using an async keyword on a method, the original asynchronous method creates a state machine instance, initializes it with the captured state (including this pointer if the method is not static), and then starts the execution by calling AsyncTaskMethodBuilder<T>.Start with the state machine instance passed by reference.
As soon as control reaches an await keyword, the current thread (which can be a .Net thread pool's worker thread), creates a callback (as a delegate) to execute the rest of the sync code exactly after the await keyword (Continuation) using the SynchronizationContext/TaskSheduler's APIs (SynchronizationContext may not be present in all applications, such as Console Applications or ASP.Net Core Web Applications), the captured SynchronizationContext is stored in the state machine as an object, the IO work is sent to an IOCP thread, and the current thread is then released.
The IOCP thread binds to an IOCP (IO Completion Port), opens a connection, and asks it to execute the code that has been waited, and the IOCP sends the execution command to the corresponding device (socket/drive).
Whenever the IO work is finished by the relevant device, a signal from the IOCP is returned to the IOCP thread along with the result of the IO work, and then the IOCP thread, based on that captured SynchronizationContext determines which thread of thread pool should process the continuation/callback (that was stored in the state machine).
Also, the following articles can be useful:
https://devblogs.microsoft.com/premier-developer/dissecting-the-async-methods-in-c/
https://tooslowexception.com/net-asyncawait-in-a-single-picture/
https://devblogs.microsoft.com/dotnet/configureawait-faq/#what-is-a-synchronizationcontext
No. Current thread actually doesn't go to sleep. The execution continues. This is the whole trick of it. You may have some code that processes data while asynchronous actions are still pending. It means that by the time those async completes your main thread is free to run and process other data.
As for the other part of the question - async just executes on another thread, not the current one. I believe that CLR is responsible for spinning those threads, so that many async actions are allowed at the same time (i.e. you may be retrieving data asynchronously from different web servers at the same time).
Related
JavaScript callback runs only when the call stack is empty. That happens either when the program execution finishes or when the main program calls await.
The callback in case of Task library in C#:
Assuming single thread program, behaves the same as JS (assuming await is used and not .Wait which would cause deadlock).
However in case of using Task.Run, or configure await false, the callback will run immediately when the response is ready. I am assuming each thread has its own call stack.
Is this correct distinction between when the callback runs in case of JS and C#?
Is this correct distinction between when the callback runs in case of JS and C#?
Not really.
In JavaScript, the continuation always runs on the main thread when it is not doing anything else. Even if you await a Promise that's already complete, it's as though you called setTimeout without a delay. The code always yields whenever there's an await. IMO, the JavaScript approach is cleaner and easier to understand than C#. However, the .NET team adopted a different approach for C#, I assume for performance reasons.
In C#, the first thing to note is that await may continue executing synchronously. If the awaitable is already complete, then there's no yielding that takes place and no continuation exists at all - the code just continues executing in the same method. If the awaitable is not already complete, then a continuation is attached to the awaitable along with the current context (SynchronizationContext.Current or TaskScheduler.Current).
When the awaitable completes, then it executes all its continuations. If it's possible, then the continuation is executed on the current thread (the one that completed the awaitable). If this kind of "inline continuation" isn't possible, then the continuation is queued to the context (SynchronizationContext / TaskScheduler). What happens then is entirely dependent on the context. E.g., UI contexts will queue continuations to the UI message processing loop, which is pretty much the same as setTimeout in JavaScript. As another example, the thread pool context will queue continuations to the thread pool.
Main difference is: single-thread vs multi-thread
I think, in your case, callback is called from different thread.
Learn more about TaskScheduler and SynchronizationContext to achieve your endeavour.
I would like to preface this question with the following:
I'm familiar with the IAsyncStateMachine implementation that the await keyword in C# generates.
My question is not about the basic flow of control that ensures when you use the async and await keywords.
Assumption A
The default threading behaviour in any threading environment, whether it be at the Windows operating system level or in POSIX systems or in the .NET thread pool, has been that when a thread makes a request for an I/O bound operation, say for a disk read, it issues the request to the disk device driver and enters a waiting state. Of course, I am glossing over the details because they are not of moment to our discussion.
Importantly, that thread can do nothing useful until it is unblocked by an interrupt from the device driver notifying it of completion. During this time, the thread remains on the wait queue and cannot be re-used for any other work.
I would first like a confirmation of the above description.
Assumption B
Secondly, even with the introduction of TPL, and its enhancements done in v4.5 of the .NET framework, and with the language level support for asynchronous operations involving tasks, this default behaviour described in Assumption A has not changed.
Question
Then, I'm at a loss trying to reconcile Assumptions A and B with the claim that suddenly emerged in all TPL literature that:
When the, say, main thread, starts this request for this I/O bound
work, it immediately returns and continues executing the rest of
the queued up messages in the message pump.
Well, what makes that thread return back to do other work? Isn't that thread supposed to be in the waiting state in the wait queue?
You might be tempted to reply that the code in the state machine launches the task awaiter and if the awaiter hasn't completed, the main thread returns.
That beggars the question -- what thread does the awaiter run on?
And the answer that springs up to mind is: whatever the implementation of the method be, of whose task it is awaiting.
That drives us down the rabbit hole further until we reach the last of such implementations that actually delivers the I/O request.
Where is that part of the source code in the .NET framework that changes this underlying fundamental mechanism about how threads work?
Side Note
While some blocking asynchronous methods such as WebClient.DownloadDataTaskAsync, if one were to follow their code
through their (the method's and not one's own) oval tract into their
intestines, one would see that they ultimately either execute the
download synchronously, blocking the current thread if the operation
was requested to be performed synchronously
(Task.RunSynchronously()) or if requested asynchronously, they
offload the blocking I/O bound call to a thread pool thread using the
Asynchronous Programming Model (APM) Begin and End methods.
This surely will cause the main thread to return immediately because
it just offloaded blocking I/O work to a thread pool thread, thereby
adding approximately diddlysquat to the application's scalability.
But this was a case where, within the bowels of the beast, the work
was secretly offloaded to a thread pool thread. In the case of an API
that doesn't do that, say an API that looks like this:
public async Task<string> GetDataAsync()
{
var tcs = new TaskCompletionSource<string>();
// If GetDataInternalAsync makes the network request
// on the same thread as the calling thread, it will block, right?
// How then do they claim that the thread will return immediately?
// If you look inside the state machine, it just asks the TaskAwaiter
// if it completed the task, and if it hasn't it registers a continuation
// and comes back. But that implies that the awaiter is on another thread
// and that thread is happily sleeping until it gets a kick in the butt
// from a wait handle, right?
// So, the only way would be to delegate the making of the request
// to a thread pool thread, in which case, we have not really improved
// scalability but only improved responsiveness of the main/UI thread
var s = await GetDataInternalAsync();
tcs.SetResult(s); // omitting SetException and
// cancellation for the sake of brevity
return tcs.Task;
}
Please be gentle with me if my question appears to be nonsensical. The extent of knowledge of things in almost all matters is limited. I am just learning anything.
When you are talking about an async I/O operation, the truth, as pointed out here by Stephen Cleary (http://blog.stephencleary.com/2013/11/there-is-no-thread.html) is that there is no thread. An async I/O operation is completed at a lower level than the threading model. It generally occurs within interrupt handler routines. Therefore, there is no I/O thread handling the request.
You ask how a thread that launches a blocking I/O request returns immediately. The answer is because an I/O request is not at its core actually blocking. You could block a thread such that you are intentionally saying not to do anything else until that I/O request finishes, but it was never the I/O that was blocking, it was the thread deciding to spin (or possibly yield its time slice).
The thread returns immediately because nothing has to sit there polling or querying the I/O operation. That is the core of true asynchronicity. An I/O request is made, and ultimately the completion bubbles up from an ISR. Yes, this may bubble up into the thread pool to set the task completion, but that happens in a nearly imperceptible amount of time. The work itself never had to be ran on a thread. The request itself may have been issued from a thread, but as it is an asynchronous request, the thread can immediately return.
Let's forget C# for a moment. Lets say I am writing some embedded code and I request data from a SPI bus. I send the request, continue my main loop, and when the SPI data is ready, an ISR is triggered. My main loop resumes immediately precisely because my request is asynchronous. All it has to do is push some data into a shift register and continue on. When data is ready for me to read back, an interrupt triggers. This is not running on a thread. It may interrupt a thread to complete the ISR, but you could not say that it actually ran on that thread. Just because its C#, this process is not ultimately any different.
Similarly, lets say I want to transfer data over USB. I place the data in a DMA location, set a flag to tell the bus to transfer my URB, and then immediately return. When I get a response back it also is moved into memory, an interrupt occurs and sets a flag to let the system know hey, heres a packet of data sitting in a buffer for you.
So once again, I/O is never truly blocking. It could appear to block, but that is not what is happening at the low level. It is higher level processes that may decide that an I/O operation has to happen synchronously with some other code. This is not to say of course that I/O is instant. Just that the CPU is not stuck doing work to service the I/O. It COULD block if implemented that way, and this COULD involve threads. But that is not how async I/O is implemented.
For long running operation, if the asp.net thread is freed up to server other requests. On which thread does the long running operation will get executed and how will it acquire asp.net thread upon its completion.
As I describe on my blog, long-running I/O operations do not require a thread at all. Rather, they use naturally-asynchronous I/O, which does not require a thread.
Device drivers generally use DMA, and this allows the device to directly read/write out of the main system RAM. .NET complements this approach with an IOCP (I/O Completion Port) that is part of the thread pool, allowing a single thread (or very few threads) per appdomain to wait on huge numbers of I/O operations.
To answer the second half of your question, the asynchronous method will resume with the request context, but it might or might not be on the same thread it was on before the await. The more common scenario is when the I/O operation completes, it signals the IOCP, which takes a thread pool thread to do a bit of housekeeping (marking the Task as complete, etc), and then that same thread enters the ASP.NET request context and resumes executing the handler. This doesn't always happen - sometimes a thread switch is necessary - but it's the most common case.
To answer your question, All threads are drawn from the thread pool.
An example scenario can be given like this, when a request is received by the server, an available thread is drawn from the pool to service the request.
Then you spawn a new thread (either by Async or other means). Now a new thread is drawn from the pool to run the request of your Async body.
Meanwhile the original thread is freed to the pool and goes back to process another request.
When your threading is finished, it fetches back another thread (may not be the same as original thread) from pool and completes your request.
It's a complete waste of time if this process is CPU bound since you are blocking one thread (which is from the same pool). However IO bound operations can be processed like this, since they use no threads.
I have a TPL Task that does two things. First, it calls a web service. Second, it inserts some data into a database. I have up to 20 Tasks started at one time doing this same thing over and over again. All they do all day is call web services and insert data into a database.
I'm fairly new to TPL in .NET. I've done some stuff with background worker processes and async web services.
The web service call and the database insert are both blocking calls within the thread the Task is running in.
I understand that under the covers, when you use Tasks, .NET manages a thread pool for you. Yes?
Would the thread pool have more threads at its disposal if I made the service call and database call with async and await() instead of making them blocking calls?
My theory (and I'm not sure why I think this) is that the thread is busy doing nothing while waiting on the blocking web service and can't return its resources temporarily to the pool. But I wonder if the Tasks were waiting for async calls to finish whether the main Task thread would be able to switch to let other stuff process while waiting.
Is my theory right? Or am I making stuff up?
I'm using c# and .NET 4.0, but I could go to 4.5 if needed.
Would the thread pool have more threads at its disposal if I made the
service call and database call with async and await() instead of
making them blocking calls?
It depends on what you mean by "making use of async-await".
When you use Task.Run, behind the scenes, the Task class uses the ThreadPool to offload work using a ThreadPool thread.
If your service doesn't expose a true async api and you uses Task.Run to queue your work, you will still be blocking a threadpool thread to do IO bound work, regardless of the use of async-await. In your question you state that both calls are blocking calls, and in that case the answer is no, the threadpool thread used to make those blocking calls woul still be blocked.
If your service and database calls were true async APIs (one that doesn't consume any extra threads to do its work), you could advantage of async-await, as when you await on one of those calls (and you shouldn't need to use Task.Run with them at all), the current thread will yield control back to the caller, and can be used in the meanwhile to do more work. If this is the case, then yes.
My theory (and I'm not sure why I think this) is that the thread is busy doing nothing while waiting on the blocking web service and can't return its resources temporarily to the pool. But I wonder if the Tasks were waiting for async calls to finish whether the main Task thread would be able to switch to let other stuff process while waiting.
Your theory is correct. If the main job of the queued threadpool work is to make an IO bound request then its spending of most its time simply blocking until the request finishes.
When you await a Task, control yields back to caller. Lets assume your service call was a REST call, you could use HttpClient which exposes true non-thread consuming async methods such as GetAsync, PostAsync, and when you await these calls, your calling thread is released to do more work in the meanwhile.
If all an application's tasks block, each task will use a thread from the thread pool.
If all tasks regularly await, the thread pool does not need to use a thread for every task.
When your code awaits an operation that hasn't completed yet, the method's state is saved such that it can be resumed on any other thread.
Idle threadpool threads get released after a while, so the actual thread which hits an await can be released from the thread pool while the method calling await is still running.
Putting all this together, an async version of a routine can do the same work with less threads (assuming the workload has enough balance of time awaiting vs spinning the CPU).
This code runs 100 tasks doing a synchronous wait:
var numTasks = 100;
for (int i = 0; i < numTasks; i++)
{
Thread.Sleep(5);
Task.Run(() =>
{
Thread.Sleep(5000);
Interlocked.Decrement(ref numTasks);
});
}
while (numTasks > 0) Thread.Sleep(100);
For the async wait, change it to:
Task.Run(async () =>
{
await Task.Delay(5000);
Interlocked.Decrement(ref numTasks);
});
On my system the async version grows the peak thread count half as much, and takes 20% of the time to do the same 'work'.
The answer is yes. Although technically it's not "waiting" for the async operation to complete (otherwise there would be no benefit to async). Under the hood there is a callback delegate that is run when the async operation completes, which is what allows your calling thread to proceed without blocking. It's the async/await magic that turns these 'continuations' into a linear looking piece of code.
Because you are using a threadpool thread, when it hits an await the thread will return to the threadpool. The thing to be careful with here is that the normal behaviour is when the awaited operation completes it will try to get back onto the thread that it was started on (now probably being used by another Task) so you may observe latency problems in getting the results back as threadpool threads are now tied up starting other tasks. Over time the threadpool will try to adjust the number of available threads to meet demand but you might find this doesn't happen quickly enough if you work comes in bursts. The result will be apparently poor performance as you may only have a small number of threads available.
I've been reading some async articles here: http://www.asp.net/web-forms/tutorials/aspnet-45/using-asynchronous-methods-in-aspnet-45 and the author says :
When you’re doing asynchronous work, you’re not always using a thread.
For example, when you make an asynchronous web service request,
ASP.NET will not be using any threads between the async method call
and the await.
So what I am trying to understand is, how does it become async if we don't use any Threads for concurrent execution? What does it mean "you're not always using a thread."?
Let me first explain what I know regarding working with threads (A quick example, of course Threads can be used in different situations other than UI and Worker methodology here)
You have UI Thread to take input, give output.
You can handle things in UI Thread but it makes the UI unresponsive.
So lets say we have a stream-related operation and we need to download some sort of data.
And we also allow users to do other things while it is being downloaded.
We create a new worker thread which downloads the file and changes the progress bar.
Once it is done, there is nothing to do so thread is killed.
We continue from UI thread.
We can either wait for the worker thread in UI thread depending on the situation but before that while the file is being downloaded, we can do other things with UI thread and then wait for the worker thread.
Isn't the same for async programming? If not, what's the difference? I read that async programming uses ThreadPool to pull threads from though.
Threads are not necessary for asynchronous programming.
"Asynchronous" means that the API doesn't block the calling thread. It does not mean that there is another thread that is blocking.
First, consider your UI example, this time using actual asynchronous APIs:
You have UI Thread to take input, give output.
You can handle things in UI Thread but it makes the UI unresponsive.
So lets say we have a stream-related operation and we need to download some sort of data.
And we also allow users to do other things while it is being downloaded.
We use asynchronous APIs to download the file. No worker thread is necessary.
The asynchronous operation reports its progress back to the UI thread (which updates the progress bar), and it also reports its completion to the UI thread (which can respond to it like any other event).
This shows how there can be only one thread involved (the UI thread), yet also have asynchronous operations going on. You can start up multiple asynchronous operations and yet only have one thread involved in those operations - no threads are blocked on them.
async/await provides a very nice syntax for starting an asynchronous operation and then returning, and having the rest of the method continue when that operation completes.
ASP.NET is similar, except it doesn't have a main/UI thread. Instead, it has a "request context" for every incomplete request. ASP.NET threads come from a thread pool, and they enter the "request context" when they work on a request; when they're done, they exit their "request context" and return to the thread pool.
ASP.NET keeps track of incomplete asynchronous operations for each request, so when a thread returns to the thread pool, it checks to see if there are any asynchronous operations in progress for that request; if there are none, then the request is complete.
So, when you await an incomplete asynchronous operation in ASP.NET, the thread will increment that counter and return. ASP.NET knows the request isn't complete because the counter is non-zero, so it doesn't finish the response. The thread returns to the thread pool, and at that point: there are no threads working on that request.
When the asynchronous operation completes, it schedules the remainder of the async method to the request context. ASP.NET grabs one of its handler threads (which may or may not be the same thread that executed the earlier part of the async method), the counter is decremented, and the thread executes the async method.
ASP.NET vNext is slightly different; there's more support for asynchronous handlers throughout the framework. But the general concept is the same.
For more information:
My async/await intro post tries to be both an intro yet also reasonably complete picture of how async and await work.
The official async/await FAQ has lots of great links that go into a lot of detail.
The MSDN magazine article It's All About the SynchronizationContext exposes some of the plumbing underneath.
First time when I saw async and await, I thougth they were C# Syntactic sugar for Asynchronous Programming Model. I was wrong, async and await are more than that. It is a brand new asynchronous pattern Task-based Asynchronous Pattern, http://www.microsoft.com/en-us/download/details.aspx?id=19957 is a good article to get start. Most of the FCL classes which inplement TAP are call APM methods (BegingXXX() and EndXXX()). Here are two code snaps for TAP and AMP:
TAP sample:
static void Main(string[] args)
{
GetResponse();
Console.ReadLine();
}
private static async Task<WebResponse> GetResponse()
{
var webRequest = WebRequest.Create("http://www.google.com");
Task<WebResponse> response = webRequest.GetResponseAsync();
Console.WriteLine(new StreamReader(response.Result.GetResponseStream()).ReadToEnd());
return response.Result;
}
APM sample:
static void Main(string[] args)
{
var webRequest = WebRequest.Create("http://www.google.com");
webRequest.BeginGetResponse(EndResponse, webRequest);
Console.ReadLine();
}
static void EndResponse(IAsyncResult result)
{
var webRequest = (WebRequest) result.AsyncState;
var response = webRequest.EndGetResponse(result);
Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
}
Finally these two will be the same, because GetResponseAsync() call BeginGetResponse() and EndGetResponse() inside. When we reflector the source code of GetResponseAsync(), we will get code like this:
task = Task<WebResponse>.Factory.FromAsync(
new Func<AsyncCallback, object, IAsyncResult>(this.BeginGetResponse),
new Func<IAsyncResult, WebResponse>(this.EndGetResponse), null);
For APM, in the BeginXXX(), there is an argument for a callback method which will invoked when the task (typically is an IO heavy operation) was completed. Creating a new thread and asynchronous, both of them will immediately return in main thread, both of them are unblocked. On performance side, creating new thread will cost more resource when process I/O-bound operations such us read file, database operation and network read. There are two disadvantages in creating new thread,
like in your mentioned article, there are memory cost and CLR are
limitation on thread pool.
Context switch will happen. On the other hander, asynchronous will
not create any thread manually and it will not have context switch
when the the IO-bound operations return.
Here is an picture which can help to understand the differences:
This diagram is from a MSDN article "Asynchronous Pages in ASP.NET 2.0", which explain very detail about how the old asynchronous working in ASP.NET 2.0.
About Asynchronous Programming Model, please get more detail from Jeffrey Richter's article "Implementing the CLR Asynchronous Programming Model", also there are more detail on his book "CLR via Csharp 3rd Edition" in chapter 27.
Let’s imagine that you are implementing a web application and as each client request comes in to
your server, you need to make a database request. When a client request comes in, a thread pool
thread will call into your code. If you now issue a database request synchronously, the thread will block
for an indefinite amount of time waiting for the database to respond with the result. If during this time
another client request comes in, the thread pool will have to create another thread and again this
thread will block when it makes another database request. As more and more client requests come in,
more and more threads are created, and all these threads block waiting for the database to respond.
The result is that your web server is allocating lots of system resources (threads and their memory) that
are barely even used!
And to make matters worse, when the database does reply with the various results, threads become
unblocked and they all start executing. But since you might have lots of threads running and relatively
few CPU cores, Windows has to perform frequent context switches, which hurts performance even
more. This is no way to implement a scalable application.
To read data from the file, I now call ReadAsync instead of Read. ReadAsync internally allocates a
Task object to represent the pending completion of the read operation. Then, ReadAsync
calls Win32’s ReadFile function (#1). ReadFile allocates its IRP, initializes it just like it did in the
synchronous scenario (#2), and then passes it down to the Windows kernel (#3). Windows adds the IRP
to the hard disk driver’s IRP queue (#4), but now, instead of blocking your thread, your thread is
allowed to return to your code; your thread immediately returns from its call to ReadAsync (#5, #6,
and #7). Now, of course, the IRP has not necessarily been processed yet, so you cannot have code after
ReadAsync that attempts to access the bytes in the passed-in Byte[].