Does async really enable callers to await? - c#

MSDN says:
If you specify that a method is an async method by using an Async or async modifier, you enable the following two capabilities... The marked async method can itself be awaited by methods that call it.
But another page gives this example:
private async Task SumPageSizesAsync()
{
// To use the HttpClient type in desktop apps, you must include a using directive and add a
// reference for the System.Net.Http namespace.
HttpClient client = new HttpClient();
// . . .
Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
byte[] urlContents = await getContentsTask;
// Equivalently, now that you see how it works, you can write the same thing in a single line.
//byte[] urlContents = await client.GetByteArrayAsync(url);
// . . .
}
Here we see it call a function GetByteArrayAsync which is not equipped with the async keyword, and yet the caller is able to await on the result.
Is MSDN wrong when it says that the async modifier enables callers to await?
From the caller's perspective, what's the difference between a function that returns Task<T>, and the same function marked as async?

Is MSDN wrong when it says that the async modifier enables callers to await?
No. It does allow callers to await as it rewrites your method to return a Task/Task<T>. But it isn't the only way to do so. Any method that returns an awaitable (e.g. Task<bool>, YieldAwaitable) enables the callers to await.
From the caller's perspective, what's the difference between a function that returns Task<T>, and the same function marked as async?
If it's implemented correctly, there shouldn't be any difference. The async and await keywords are a way for the compiler to help you write asynchronous code. But they are not necessary. You can (and you always could have) write asynchronous code without them.
Take Task.Delay for example. It creates a task, sets a timer, configures the timer to complete the task after some time and returns the task. It doesn't use async-await and it doesn't need to. But by returning a task it allows the caller to await it.
In fact, a lot of the task-returning methods in the .NET framework don't use async-await internally as they are the "root" asynchronous methods. They return a task but don't have a task to await themselves.

Do do not await a function, you await a Task or a Task<T> that a function returns1. In any examples where you see await client.GetByteArrayAsync(url) there is a hidden implicit Task<byte[]> that gets "passed" between the client.GetByteArrayAsync(url) and the await.
You question is similar to asking "How does the + work when you do
int result = 1 + 2;
vs when you do
int two = 2;
int result = 1 + two;
The documentation states it is for adding two numbers together, but I am not adding two numbers in the 2nd example I am adding a number and a variable."
1: It is a little more completed than that, but for 99% of the time just think of it that way.

From async/await faq (emphasis mine):
What does the “async” keyword do when applied to a method?
When you mark a method with the “async” keyword, you’re really telling
the compiler two things:
You’re telling the compiler that you want to be able to use the “await” keyword inside the method (you can use the await keyword if
and only if the method or lambda it’s in is marked as async). In doing
so, you’re telling the compiler to compile the method using a state
machine, such that the method will be able to suspend and then resume
asynchronously at await points.
You’re telling the compiler to “lift” the result of the method or any exceptions that may occur into the return type. For a method that
returns Task or Task, this means that any returned value or
exception that goes unhandled within the method is stored into the
result task. For a method that returns void, this means that any
exceptions are propagated to the caller’s context via whatever
“SynchronizationContext” was current at the time of the method’s
initial invocation.
So, think of it as a syntactic sugar over plain old asynchronous .NET model: more compiler checks, less code, and completely indifferent from the caller perspective (caller either awaits the result inside async method or uses other TPL primitives, or even blocks).
Actually, if you check the source code of the GetByteArrayAsync method, it is simply a wrapper over GetContentAsync method constructing the resulting Task with TaskCompletionSource and continuation-passing style.
private Task<T> GetContentAsync<T>(Uri requestUri, HttpCompletionOption completionOption, T defaultValue,
Func<HttpContent, Task<T>> readAs)
{
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
GetAsync(requestUri, completionOption).ContinueWithStandard(requestTask =>
{
if (HandleRequestFaultsAndCancelation(requestTask, tcs))
{
return;
}
HttpResponseMessage response = requestTask.Result;
if (response.Content == null)
{
tcs.TrySetResult(defaultValue);
return;
}
try
{
readAs(response.Content).ContinueWithStandard(contentTask =>
{
if (!HttpUtilities.HandleFaultsAndCancelation(contentTask, tcs))
{
tcs.TrySetResult(contentTask.Result);
}
});
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
});
return tcs.Task;
}

An async modifier allows you to use the await keyword within that method. Any Task can be awaited within a method marked async -- the Task represents an ongoing activity that may or may not already be complete when it is returned to the caller.

As far as I can tell it's not being awaited. The Task is.
The marked async method can itself be awaited - that's for methods. A Task doesn't need that in order to be awaitable (which is what you're doing in await getContentsTask).
This also answers part 2 - The difference is that the one that returns Task and is not marked async cannot be awaited. Which is what MSDN says in the quoted text.
(I might be wrong, of course.)

Related

async await methods don't work parallel on calling controller action method

i have a simple controller with two methods Index and IndexAsync synchronous and asynchronous respectively. I try to do same as written in this article. But something going wrong , instead of 5 seconds result i get 12. How come , what's the reason ?
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpGet]
public async Task<string> IndexAsync()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
await Delay(3);
await Delay(5);
await Delay(4);
stopwatch.Stop();
return stopwatch.Elapsed.Seconds.ToString();
}
private async Task<Int32> Delay(int sec)
{
await Task.Delay(1000 * sec);
return sec;
}
}
the result:
Many people have a bad model in their heads of what await does. Despite it's name, they somehow come to believe that it starts things happening. Nothing could be further from the truth1.
await has some expression on its right-hand side. It doesn't care what that expression is, how it goes about its work, etc. All it cares about is that the expression is going to produce something that is awaitable2. By far the most common awaitables you'll encounter are Task and Task<T>.
And then await does its simple job - is this awaitable thing finished? If so, we'll get the result (if any) and then carry on. If not, then we can't make any further progress. If someone else can make good use of our thread in the meantime, we'll let that happen. And when that awaitable thing does finish, we've arranged to resume execution of the method containing the await.
I will just reiterate - await doesn't care how or why that awaitable got created. That's someone else's job - here, it's being done by the async machinery that transformed your Delay method. But await doesn't care that that method is marked async (that's an implementation detail of that method, not part of its signature, despite where it appears), just that it promises to return a "hot" Task - one that's already running.
1I think it's mostly because some people have learned the approximate equality async ≅ parallelism ≅ using threads. It was never really true but this is what we're constantly fighting to correct. And so they think "async must mean we're creating threads"
2Indeed, in the article you linked to, and the issue already addressed by Rawling the expressions there referred to variables that had previously been initialized by calls to Task-returning methods. Which is what made your own code different.
In the article, the code starts all three tasks and then awaits all three tasks:
var contentTask = service.GetContentAsync(); // start task 1
var countTask = service.GetCountAsync();
var nameTask = service.GetNameAsync();
var content = await contentTask; // wait until task 1 is finished
var count = await countTask;
var name = await nameTask;
Your code starts and awaits each task in turn:
await Delay(3); // start task 1 and wait until it is finished
await Delay(5);
await Delay(4);
Make the following code modification, for the Async calls to be executed together not one after another :
var result = await Task.WhenAll(Delay(3),Delay(4),Delay(5));
Task.WhenAll will provide the representative Task, which will finish, when all the tasks in the collection supplied are finished execution (Success / Failure). So we just await the representative task and get the necessary behavior, though it still may not guarantee 5 sec as expected. result will be an int[], which will contain value from each call to Delay method.
In your case, the Delay method takes the responsibility of beginning the Task, using await Task.Delay(1000 * sec);, therefore if you just call the Delay as shown by the accepted answer, then separately await, then they still get executed in parallel, but let's assume, you are not sure or the Delay method is as follows:
private Task Delay(int sec)
{
return Task.Delay(1000 * sec);
}
then using await Task.WhenAll(...) becomes important, since it will start the tasks which are not started, otherwise will simply wait for them to finish. Otherwise using the accepted answer you will not receive the benefit.
More regarding await as general information, from the C# 6.0 specification guide:
Awaitable expressions
The task of an await expression is required to be awaitable. An expression t is awaitable if one of the following holds:
t is of compile time type dynamic
t has an accessible instance or extension method called GetAwaiter with no parameters and no type parameters, and a return type A for which all of the following hold:
A implements the interface System.Runtime.CompilerServices.INotifyCompletion (hereafter known as
INotifyCompletion for brevity)
A has an accessible, readable instance property IsCompleted of type bool
A has an accessible instance method GetResult with no parameters and no type parameters.
The purpose of the GetAwaiter method is to obtain an awaiter for the task. The type A is called the awaiter type for the await expression.
The purpose of the IsCompleted property is to determine if the task is already complete. If so, there is no need to suspend evaluation.
The purpose of the INotifyCompletion.OnCompleted method is to sign up a "continuation" to the task; i.e. a delegate (of type System.Action ) that will be invoked once the task is complete.
The purpose of the GetResult method is to obtain the outcome of the task once it is complete.
This outcome may be successful completion, possibly with a result value, or it may be an exception which is thrown by the GetResult method.
Classification of await expressions
The expression await t is classified the same way as the expression (t).GetAwaiter().GetResult() . Thus, if the return type of GetResult is void, the await_expression is classified as nothing. If it has a non-void return type T , the await_expression is classified as a value of type T.
Runtime evaluation of await expressions
At runtime, the expression await t is evaluated as follows:
An awaiter a is obtained by evaluating the expression (t).GetAwaiter()
A bool b is obtained by evaluating the expression (a).IsCompleted
If b is false then evaluation depends on whether a implements the interface
System.Runtime.CompilerServices.ICriticalNotifyCompletion (hereafter known as ICriticalNotifyCompletion for brevity). This check is done at binding time; i.e. at runtime if a has the compile time type dynamic , and at compile time otherwise. Let r denote the resumption delegate (Iterators):
If a does not implement ICriticalNotifyCompletion , then the expression
(a as (INotifyCompletion)).OnCompleted(r) is evaluated.
If a does implement ICriticalNotifyCompletion , then the expression
(a as (ICriticalNotifyCompletion)).UnsafeOnCompleted(r) is evaluated.
Evaluation is then suspended, and control is returned to the current caller of the async function.
Either immediately after (if b was true ), or upon later invocation of the resumption delegate (if b was false ), the expression (a).GetResult() is evaluated. If it returns a value, that value is the result of the
await_expression. Otherwise the result is nothing.
An awaiter's implementation of the interface methods INotifyCompletion.OnCompleted and ICriticalNotifyCompletion.UnsafeOnCompleted should cause the delegate r to be invoked at most once. Otherwise, the behavior of the enclosing async function is undefined.

Is it useful to mark a method async when it only awaits at the return statement? [duplicate]

This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 2 years ago.
Only the last line of the method below is using 'await', just before the method returns, so doesn't this mean that method is basically synchronous and should just be called "Get()" without the async modifier and the suffix Async?
public virtual async Task<TEntity> GetAsync(Guid id)
{
// some more code here
return await _dbSet.FindAsync(id);
}
doesn't this mean that method is basically synchronous
No. It's asynchronous. You're probably thinking of sequential (progressing from one thing to the next), not synchronous (blocking the current thread). An await will pause the method (sequentially) but not block the thread (asynchronously). For more information, see my async intro.
without the async modifier
While you could elide the async/await keywords, I would recommend that you do not. This is because // some more code here may throw an exception. I cover this and other considerations in my blog post on eliding async and await.
and the suffix Async?
No, that suffix is appropriate for any method that returns an awaitable (e.g., Task). So, even if you elide the async and await, it's still returning a task that should be awaited, so it should still have the Async suffix.
You can think of it this way: the Async suffix is part of the API interface. The async keyword is an implementation detail. They often go together, but not always.
Its a matter of opinion. Generally the naming convention is anything that returns Task or Task<T> has a suffix of Async.
Your example above though would be better written like this so you do not have the extra overhead of the async wrapper. This is because you do not need to await the result in that method. The consumer of the method would then await the result if it used it directly.
public virtual Task<TEntity> GetAsync(Guid id, params Expression<Func<TEntity, object>>[] includeProperties))
{
// some more code here
return _dbSet.FindAsync(id);
}
await doesn't block. It awaits asynchronously for an operation to complete. That means that the original thread is released while awaiting. In a desktop application, this means that the UI thread is released while waiting eg for an HTTP or database call to finish.
When that operation completes, execution is returned to the original thread (for desktop applications).
As it is, you can simplify your code by removing the async and await keywords and returning the Task immediatelly. The code doesn't do anything with the results of the operation, so it doesn't need to await for it to finish. This will be done by the caller of the method:
public virtual Task<TEntity> GetAsync(Guid id)
{
// some more code here
return _dbSet.FindAsync(id);
}
The real asynchronous operation in this code is FindAsync. The async keyword is just syntactic sugar that allows you to use the await keyword. If you don't need to await, you don't need the async keyword either
There are many cases where suffixing every async method with Async is simply redundant. If your method returns a Task or Task<T>, and its purpose is to get data from a database or another network resource, then of course it runs asynchronously. The compiler will also almost always give you an error if you forget to await something. With that in mind, there are some good reasons to suffix async methods with Async:
The method runs asynchronously but does not return a Task
There is an alternative other method by the same name that runs synchronously
Forgetting an await in calling code is unlikely to be caught by the compiler
Suffixing a method name with Async is meant to indicate that the method runs asynchronously, which this method does. Whether it does so using async/await or directly returns another Task is an implementation detail. Imagine you were reviewing some code calling the method that forgets to use await. Which of these makes the error more apparent?
var item1 = _example.Get(itemId1);
var item2 = _example.GetAsync(itemId2);
Based on nothing else, there's no reason to believe there's anything wrong with the first line. The second line will at least raise some eyebrows.

Can we turn async methods into expression body?

I was reading this article about Expression Bodied Members in C# 6.0, the author demonstrated this code:
public async Task<string> ReadFromWeb() => await RunWebRequest();
He says that it's not recommended to use async and await keywords in above code:
The compiler is performing some heavy lifting to implement the async
state machine for this method. Because of the structure of the method,
that extra work isn't really accomplishing much. It's creating a state
machine to wrap a task that simply unwraps a task returned from a
different method.
He proposed that we should write the code without async and await:
public Task<string> ReadFromWebSimple() => RunWebRequest();
I'd like to know more information about that.
Lets see what the author was talking about. When you mark a method as async, the compiler generates a state-machine on your behalf in order to allow the asynchronous style of execution to "feel like" it's executing synchronously.
When you write:
public async Task<string> ReadFromWeb() => await RunWebRequest();
The compiler generates:
[AsyncStateMachine(typeof(C.<RunWebRequest>d__1))]
public Task<string> RunWebRequest()
{
C.<RunWebRequest>d__1 <RunWebRequest>d__;
<RunWebRequest>d__.<>t__builder = AsyncTaskMethodBuilder<string>.Create();
<RunWebRequest>d__.<>1__state = -1;
AsyncTaskMethodBuilder<string> <>t__builder = <RunWebRequest>d__.<>t__builder;
<>t__builder.Start<C.<RunWebRequest>d__1>(ref <RunWebRequest>d__);
return <RunWebRequest>d__.<>t__builder.Task;
}
Since you're using an Expression Bodied Method, you actually have a single liner of a method. When do you generally await on something? when you want to manipulate the return value of the async method. With one-liners, that's never the case. This means that you can save the state-machine generation at the invocation level, and let only those who want to acutally await the result higher up the caller stack to await on your method. This will effectively transform your method to look like this:
public Task<string> ReadFromWeb()
{
return this.RunWebRequest();
}
Which saves you the rather already slim state-machine struct allocated by the compiler, which is actually quite redundant when you're creating an EBM.
Making a method async allows you to use await inside it. You don't really need await as you're not using the return value and you're not doing anything after that operation completes. In this case you can just return the task directly instead. That way your caller awaits the inner async method without the overhead of the method in between.
This avoids the work being done to make ReadFromWeb an async method. It's not a huge deal but in this case where all you have is a single invocation doing that is pretty harmless.

Using Async and Await in C#

I'm trying to understand async and await, and I've got a few questions. In this example from Microsoft
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
The method uses client.GetStringAsync, however, what happens if the method you're calling isn't an Async method? If I were calling for example, File.ReadAllLines(), how would I make that an Async call?
The method has a return type of Task<int>. Does any method that uses await, have to have a return type of Task<>? What if there is nothing to return?
The method uses client.GetStringAsync, however, what happens if the method you're calling isn't an Async method? If I were calling for example, File.ReadAllLines(), how would I make that an Async call?
Don't drive async from the "outside in"; rather, let it bubble up from the "inside out". In other words, if you want to make something asynchronous, you first find the lowest-level APIs that are asynchronous, then you make the calling method async.
The method has a return type of Task. Does any method that uses await, have to have a return type of Task<>? What if there is nothing to return?
Then the result type of the method should be Task.
Technically, async methods can return Task, Task<T>, or void. You should avoid async void; it should only be used for event handlers (or methods that are logically event handlers). Task<T> is a wrapper around a result type of T; this wrapper also includes information about any exceptions. Similarly, Task contains valuable information about exceptions (or successful completion).
You would call the appropriate Async method. If there isn't one, then it won't be truly asynchronous. You could "make" your own by wrapping it with Task.Run() but it really defeats the purpose of being async. This is fine in a desktop app, but it's a terrible idea to do in an ASP.NET/server scenario because you're creating more threads to handle the same functionality. (Too many threads means your throughput will suffer in server scenarios). All I/O (database ,file access) in .NET should have the appropriate Async() methods along with the standard blocking methods. For a deeper discussion on why this is a bad idea, see Stephen Taub's blog post on it.
Any method using the async/await pattern has to return a Task<>. This is because while the system is "await'ing", it will return a Task<>, which represents a future promise of the return type. The calling method can continue on if it wishes to other code, or it can stay await'ing your async method call and provide scalability benefits until the true underlying type has been returned from that async method.
If I were calling for example, File.ReadAllLines(), how would I make that an Async call?
You don't "make something" async, it has to be naturally so. Many operations are IO bound, such as a network call or accessing disk. There is no File.ReadAllLinesAsync, but you can write one yourself using a "lower-level" API such as FileStream.
Does any method that uses await, have to have a return type of Task<>? What if there is nothing to return?
No, it doesn't. A Task<T> is used when you have a return value from an asynchronous method. In your example, that value is a string. It is wrapped in a Task<> because a Task is a promise of work which will complete in the future. Awaiting on a Task<string> asynchronously waits until the async operation is done and that string is returned.

Asynchronous method that does nothing

I have an interface IAnimation which exposes a method BeginAsync(). That method should start the animation and return when it is completed.
What I would like to do is implement a null animation class NoAnimation that just returns when it executes BeginAsync().
Is this the right implementation?
public async Task BeginAsync()
{
await Task.Run(() => { });
}
I suspect that there is a more elegant approach than this. I also considered
creating an empty method. But that gives me a warning which I don't like either.
Just use Task.CompletedTask to return a completed task:
public Task BeginAsync()
{
return Task.CompletedTask;
}
If you have a Task<TResult> use Task.FromResult<TResult> to return a completed task with a result:
public Task<bool> BeginAsync()
{
return Task.FromResult(true);
}
Your current implementation is very inefficient, as it builds the state machine, and also uses a ThreadPool thread to run the empty task.
I appreciate this doesn't exactly answer the original question (or at least not in a way that isn't already in another answer). What it does it provide additional context for #ReedCopsey's answer, for those (including me! and others, based on the comments on that answer) who initially might find it hard to understand what is going on here.
It's very easy to fall into the trap of thinking that async must be part of the signature of any asynchronous method. It looks as if it must be; it (misleadingly!) reads as if it's whole purpose is to mark a method as asynchronous.
But it's not, Task or Task<T> are required, but not async. This is shown in #ReedCopsey's answer and in the following correct example (slightly adapted from this useful SO answer):
public Task<int> MethodTaskAsync(int arg0, int arg1)
{
Task<int> task = new Task<int>(() => Method(arg0, arg1));
task.Start(); // Hot task (started task) should always be returned.
return task;
}
That's why interface method signatures don't need, and can't have, the async keyword: an 'asynchronous' method per se, without regard to how it might be implemented, is just a method that returns a started (and, possibly, already finished) Task or Task<T>.
If async doesn't mark a method as asynchronous, what does it do? It's a way to write asynchronous methods more simply: once you have applied it to a method, you can use the await keyword to tell the compiler to correctly handle subsidiary asynchronous calls for you very simply (without it, you could try to handle subsidiary Tasks manually, using lots more code like that in the code block above, but to do so would be very complex and error prone).
So if you just want to return a do-nothing, already-completed task from an 'asynchronous' (i.e. Task-returning) method, you can and should do so synchronously(!), as in #ReedCopsey 's answers, using Task.CompletedTask or Task.FromResult(...).

Categories

Resources