What's the purpose of calling an async method with await on the same line? (not what is the behavior, but what are the practical uses of this pattern). As far as I understand, this will in effect be a synchronous "blocking" call, as execution in this context will not continue until GetDocumentAsync completes, correct?
Document someDocument = await db.GetDocumentAsync(documentId);
//AFAIK blocks until GetdocumentAsync completes and returns
CalledAfterAwaitReturnsAndResultIsAvailable(someDocument.SomeProperty);
Most tutorials showing how to call an async method I've seen do this, and I've seen it in other's code. To me it defeats the purpose of asynchronous execution. It would seem like to benefit from the async call, you would make the async call, without the await, and do some other unrelated sequential work(or start some other async calls) not dependent on someDocument
, and then do the await
to get the result of the async call and then do whatever depended on that return. Such that your other unrelated processing can be performed while the async call is also working in another thread. I've seen the above pattern so much, I am beginning to wonder if I am misunderstanding something.
What is the practical application of making an async call in this way, such that it blocks until it completes?
Async/Await makes it easier to write promises. The keyword ‘async’ before a function makes the function return a promise, always. And the keyword await is used inside async functions, which makes the program wait until the Promise resolves.
Calling multiple async/await functions sequential is same as call a async function with await keyword. To do this, let’s make some changes on run_processes functions so it can call all functions sequential but will results same output.
If we try to use await in a non-async function, there would be a syntax error: function f() { let promise = Promise.resolve(1); let result = await promise; // Syntax error } We may get this error if we forget to put async before a function. As stated earlier, await only works inside an async function.
It allows a program to run a function without freezing the entire program. This is done using the Async/Await keyword. Async/Await makes it easier to write promises. The keyword ‘async’ before a function makes the function return a promise, always.
The await
keyword does not call Wait
on the task, it calls ContinueWith
. The result is that rather than a blocking call, you get a completion callback.
I think the key thing you are missing is that when you hit the first await
, the function you were inside returns with a Task<Document>
(assuming your function was declared like public async Task<Document> Foo()
) and lets the person who called your function continue on doing other work.
The caller can then either process some other work and check on the Task later to see if it is done or he can await
immediately himself and continue the deferred work up the chain till you hit someone who does have work to do (on Forms or WPF this goes all the way up to the Message Pump and lets the UI keep responding while you are waiting for the task to finish).
The practical application of this pattern is when you want to trickle up/expose the async capability to other potential callers of your method. While within the context of your method it will appear to behave as if it is synchronous, it is not actually blocking. A parent caller can benefit from the child methods async capability and perform parallel processing while GetDocumentAsync processes.
public async Task<List<string>> ProcessDocument()
{
Document someDocument = await db.GetDocumentAsync(documentId);
//Since await is on the same line as the async call,
// Parse will not be called until GetDocumentAsync completes and result is available.
//Thus it appears to "block", it is not technically blocking,
// as a caller of ProcessDocument can start an async call to ProcessDocument
// and perform other parallel processing while GetDocumentAsync is processing,
// because ProcessDocument is marked async
return Parse(someDocument.Contents);
}
public async void ApplicationStart() {
//no await when calling async method, processing begins asynchrounously
Task<List<string>> parseDocTask = ProcessDocument();
//we will continue other work while ProcessDocument is asynchronously performing work
//We can execute DoIndependentWork while at the same time ProcessDocument is working on a separate thread asynchronously
DoIndependentWork();
//get result of async call, either will block until result is available,
// or if async ProcessDocument task has already completed, will continue immediately
List<string> parsedDocument = await parseDocTask;
//do something with parsedDocument
}
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