What's the new C# await feature do?
They just talked about this at PDC yesterday!
Await is used in conjunction with Tasks (parallel programming) in .NET. It's a keyword being introduced in the next version of .NET. It more or less lets you "pause" the execution of a method to wait for the Task to complete execution. Here's a brief example:
//create and run a new task
Task<DataTable> dataTask = new Task<DataTable>(SomeCrazyDatabaseOperation);
//run some other code immediately after this task is started and running
ShowLoaderControl();
StartStoryboard();
//this will actually "pause" the code execution until the task completes. It doesn't lock the thread, but rather waits for the result, similar to an async callback
// please so also note, that the task needs to be started before it can be awaited. Otherwise it will never return
dataTask.Start();
DataTable table = await dataTask;
//Now we can perform operations on the Task result, as if we're executing code after the async operation completed
listBoxControl.DataContext = table;
StopStoryboard();
HideLoaderControl();
How and when to use ‘async’ and ‘await’
When using async
and await
the compiler generates a state machine in the background.
Here's an example on which I hope I can explain some of the high-level details that are going on:
public async Task MyMethodAsync()
{
Task<int> longRunningTask = LongRunningOperationAsync();
// independent work which doesn't need the result of LongRunningOperationAsync can be done here
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation
{
await Task.Delay(1000); // 1 second delay
return 1;
}
OK, so what happens here:
Task<int> longRunningTask = LongRunningOperationAsync();
starts executingLongRunningOperation
Independent work is done on let's assume the Main Thread (Thread ID = 1) then
await longRunningTask
is reached.Now, if the
longRunningTask
hasn't finished and it is still running,MyMethodAsync()
will return to its calling method, thus the main thread doesn't get blocked. When thelongRunningTask
is done then a thread from the ThreadPool (can be any thread) will return toMyMethodAsync()
in its previous context and continue execution (in this case printing the result to the console).
A second case would be that the longRunningTask
has already finished its execution and the result is available. When reaching the await longRunningTask
we already have the result so the code will continue executing on the very same thread. (in this case printing result to console). Of course this is not the case for the above example, where there's a Task.Delay(1000)
involved.
Do the new C# 5.0 'async' and 'await' keywords use multiple cores?
Two new keywords added to the C# 5.0 language are async and await, both of which work hand in hand to run a C# method asynchronously without blocking the calling thread.
That gets across the purpose of the feature, but it gives too much "credit" to the async/await feature.
Let me be very, very clear on this point: await
does not magically cause a synchronous method to run asynchronously. It does not start up a new thread and run the method on the new thread, for example. The method you are calling has to be the thing that knows how to run itself asynchronously. How it chooses to do so is its business.
My question is, do these methods actually take advantage of multiple cores and run in parallel or does the async method run in the same thread core as the caller?
Again, that is entirely up to the method you call. All that await
does is instruct the compiler to rewrite the method into a delegate that can be passed as the continuation of the asynchronous task. That is, the await FooAsync()
means "call FooAsync()
and whatever comes back must be something that represents the asynchronous operation that just started up. Tell that thing that when it knows that the asynchronous operation is done, it should call this delegate." The delegate has the property that when it is invoked, the current method appears to resume "where it left off".
If the method you call schedules work onto another thread affinitized to another core, great. If it starts a timer that pings some event handler in the future on the UI thread, great. await
doesn't care. All it does is makes sure that when the asynchronous job is done, control can resume where it left off.
A question you did not ask but probably should have is:
When the asynchronous task is finished and control picks up where it left off, is execution in the same thread as it was before?
It depends on the context. In a winforms application where you await something from the UI thread, control picks up again on the UI thread. In a console application, maybe not.
What exactly happens when you call an async method without the await keyword?
Then my periodic job and PutRecordBatchAsync are processed concurrently?
Using Task API you can ensure that they are executed concurrently (using Thread pool), but you need to understand the difference between in memory concurrent operations Vs IO based concurrency.
While In memory concurrency does benefit using Tasks, IO call once executed doesn't need thread at all, as it relies on hardware concurrency, if it ever use the thread, all that it would do it wait for the IO call to return, thus wasting the precious system resources and reducing system scalability
You case is that IO based concurrency, as you call a remote / network based API, how does async-await helps here ?
Well true Async operation will free up the thread context, on windows it would use IO completion port (queuing mechanism) to execute the Async call, while the calling thread is used to dispatch other similar calls, it would just need thread context on return of the IO call for serving the response and for that too, if its not a UI call, then use ConfigureAwait(false)
, so that any thread context can be used to deliver the response.
What if you don't use await with async ?
The call meant to be Asynchronous becomes Synchronous and would immediately impact the system scalability, as threads are now blocked, even worse for a long running IO operations. Have you seen how JavaScript frameworks always make a AJAX (Async) call to the server API, thus much more work is possible W/o blocking the Browser threads.
In general for In memory processing you would create certain number of Tasks and process them using Task.WaitAll
or Parallel.ForEach
for a collection, for Async processing, ideally recommendation is not to have a Task.Run
anywhere, its preferred to have to Async
from the entry point, like its possible in case of MVC, controllers can be async. Multiple calls are grouped together using Task.WhenAll
representative Task and then awaited upon. even if you use Task.Run
as in your code, then use async lambda
to execute an asynchronous call
Summary :
Its mandatory to use await
for asynchronous calls, else they async
keyword is useless in that context and yes await
will wait for the IO call to return before continuation is executed, though no thread is blocked in the process
Why do we need more than one `await` statement in a C# method?
await
will wait until the operation is not executed. So you has 2 async operations, that's why you need to use await.
One await
for each async operation (method).
So, you have 3 async methods. You can call it without await, but it will crash. When you call it without await, it will start to execute in another thread, and thread where SeedAsync is executing, will not wait until InsertAsync is executed. It will start second InsertAsync at the same time
So, in your case, you can insert values without await. It will work. But in common case it's better to use await. Because often order of operations is important. await is allow to control the order of operations
Sometimes you need to run some tasks and then wait for all. Then you can use Task.WhenAll(t1,t2,t3)
Does the use of async/await create a new thread?
In short NO
From Asynchronous Programming with Async and Await : Threads
The async and await keywords don't cause additional threads to be
created. Async methods don't require multithreading because an async
method doesn't run on its own thread. The method runs on the current
synchronization context and uses time on the thread only when the
method is active. You can use Task.Run to move CPU-bound work to a
background thread, but a background thread doesn't help with a process
that's just waiting for results to become available.
Using await versus Result
Calling the Result
will block the current thread until the operation completes. The await
returns to the caller and continues with the rest of the method when the async operation is completed.
C# asynchronous functions - does await immediately start a task on a new thread?
For this function:
public async Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device)
{
return GetLanDBData(device);
}
compiler should issue a warning: "this async method lacks 'await' operators and will run synchronously". Compiler will convert this method to something like this:
public Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device)
{
var result = GetLanDBData(device);
return Task.FromResult(result);
}
So indeed compiler generated a task and returned it, but not in a way you expected. The whole method runs synchronously on caller (UI) thread and so blocks it the same way as GetLanDBData
does.
Task basically represents some work in progress (or even already completed, as shown above with Task.FromResult
), with ability to check the status of said work, and being notified when work is completed (or failed). It doesn't necessary has any relation to threads.
await someTask
very rougly means - IF someTask
is not already completed - then execute the rest of the method some time later, when someTask
actually completes. It doesn't start any new tasks, nor does it create any new threads.
Your working version:
public async Task<LanDeviceInfo> GetLanDBDataAsync(LanDeviceInfo device)
{
var deviceInfo = await Task.Run(() => GetLanDBData(device));
return deviceInfo;
}
very rougly means -
create a task representing the whole operation inside
GetLanDBDataAsync
method. Let's name thattaskResult
.Queue
GetLanDBData
to be executed on thread pool (because that's what documentation ofTask.Run
says it does, not just because "it's a task"). Task returned fromTask.Run
represents this pending operation.Now, if task returned from
Task.Run
is not yet completed (it does not) - return ourtaskResult
(representing whole operation) back to the caller.When some time later task returned from
Task.Run
completes - we execute the rest of the code. In this case, result ofTask.Run
is just forwarded to ourtaskResult
, because the rest of the code is justreturn deviceInfo
.
What does await do in this function?
It awaits the completion of the HTTP request. The code resumes (for
iteration...) only after every single request is complete.
Your 2nd version works precisely because it doesn't await for each task to complete before initiating the following tasks, and only waits for all the tasks to complete after all have been started.
What async-await is useful for is allowing the calling function to continue doing other things while the asynchronous function is awaiting, as opposed to synchronous ("normal") functions that block the calling function until completion.
Related Topics
Why Does Enumerable.All Return True for an Empty Sequence
Automapper Convert from Multiple Sources
C# - Detect Time of Last User Interaction with the Os
Most Efficient Way to Insert Rows into MySQL Database
Wpf Binding a Listbox to an Enum, Displaying the Description Attribute
C# Console Receive Input with Pipe
C# - Cannot Implicitly Convert Type List<Product> to List<Iproduct>
Hashtable with Multidimensional Key in C#
How to Check If Ienumerable Is Null or Empty
"Updatesourcetrigger=Propertychanged" Equivalent for a Windows Phone 7 Textbox
C# Open File with Default Application and Parameters
How to Bring My Application Window to the Front
Combining Two Lambda Expressions in C#
Passing List<> to SQL Stored Procedure