During my reading about Asynchronous Programming in .Net 4.5 async
and await
keywords
I read Here the following paragraph
Processing Asynchronous Requests
In web applications that sees a large number of concurrent requests at
start-up or has a bursty load (where concurrency increases suddenly),
making these web service calls asynchronous will increase the
responsiveness of your application. An asynchronous request takes
the same amount of time to process as a synchronous request. For
example, if a request makes a web service call that requires two
seconds to complete, the request takes two seconds whether it is
performed synchronously or asynchronously. However, during an
asynchronous call, a thread is not blocked from responding to other
requests while it waits for the first request to complete. Therefore,
asynchronous requests prevent request queuing and thread pool growth
when there are many concurrent requests that invoke long-running
operations.
for the bold words, I couldn't understand them how An asynchronous request takes the same amount of time to process as a synchronous request?
For example:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
await Task.Delay(1000); //1 seconds delay
return 1;
}
What I understand that LongRunningOperation()
starts execution from the first line calling here Task<int> longRunningTask = LongRunningOperation();
and returns value once calling await
,
so from my point of view asynchronous code faster than synchronous, is that right?
Another question:
What I understand that the main thread working on executing MyMethod()
not blocked waiting for LongRunningOperation()
to be accomplished but it returns to thread pool to serve another request. so is there another thread assigned to LongRunningOperation();
to execute it?
If yes so what is the difference between Asynchronous Programming and Multithreading Programming ?
Update:
let's say that code becomes like that:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
DoIndependentWork();
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
DoSomeWorkNeedsExecution();
await Task.Delay(1000); //1 seconds delay
return 1;
}
In this case , will LongRunningOperation()
be executed by another thread during DoIndependentWork()
execution?
The asynchronous operations aren't faster. If you wait for 10 seconds asynchronously (i.e. await Task.Delay(10000)
) or synchronously (i.e. Thread.Sleep(10000)
) it would take the same 10 seconds. The only difference would be that the first would not hold up a thread while waiting but the second will.
Now, if you fire up a task and don't wait for it to complete immediately you can use the same thread to do some other work, but it doesn't "speed up" the asynchronous operation's run:
var task = Task.Delay(10000);
// processing
await task; // will complete only after 10 seconds
About your second question: Task.Delay
(like other truly asynchronous operations) doesn't need a thread to be executed and so there is no thread. Task.Delay
is implemented using a System.Threading.Timer
that you fire up and it raises an event when it's done, in the meantime it doesn't need a thread because there's no code to execute.
So when the thread that was running MyMethod
reaches the await longRunningTask
it is freed (as long as longRunningTask
hasn't completed yet). If it was a ThreadPool
thread it will return to the ThreadPool
where it can process some other code in your application.
Regarding the update the flow would be so:
MyMethod
starts processing
LongRunningOperation
starts processing
DoSomeWorkNeedsExecution
is executed on the calling thread
- An
await
is reached in LongRunningOperation
and so a hot task is returned.
DoIndependentWork
is executed by the same calling thread (LongRunningOperation
is still "running", no thread is needed)
- An
await
is reached in MyMethod
. If the original task completed the same thread will proceed on synchronously, if not then a hot task would be returned that would complete eventually.
So the fact that you're using async-await
allows you to use a thread that would otherwise be blocked waiting synchronously to executed CPU-intensive work.
Consider the difference between:
Thread.Sleep(1000);
and
await Task.Delay(1000);
both will take one second to run. However in the former case the current thread will be blocked (and all its resources useless) while in the latter case the current thread can do something else that's useful (eg. serving another request).
Asynchronicity is not about speeding up individual sequences of instructions, but being able to do things when synchronous code would block.
Re. Another question
The thread(s) freed up will be used for other things; there will be no thread assigned until the operation is completed. This is possible becuase the underlying OS is itself asynchronous. In the example above a timer is used which is signalled for a thread to pick up when a thread is free, rather than a thread stopped for an internal.
(building upon I3arnon's answer)
It's not absolutely true that synchronous operations and operations using async-await
will, overall, take the same time.
There's some extra logic involved in async-await
. Checks of completed awaiters and a state machine are involved. This makes some asynchronous operations take more time than the corresponding synchronous operation.
On the other hand, most operations suited for async-await
are naturally asynchronous and there is some extra processing involved to make it look and feel synchronous. In these cases the asynchronous operation is takes less time than the synchronous counterpart.
The quote on the question is related to web applications. For web applications, asynchronous operations are more about serving the maximum number of requests on an acceptable time than saving of a few microseconds of each request. On the other hand, if a context switching is involved it ends up take more time and that's why using Task.Run
in a web application does more bad than good to the application.
If you want to learn more about async-awit
, read the articles on my async-awit
curation.