This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does the async keyword exist
I have two methods. One is a normal method (MyMethod) and one is an async method (MyMethodAsync). I get a compilation error.
static string MyMethod()
{
var result = await MyMethodAsync(); // compile error here
return result;
}
async static Task<string> MyMethodAsync()
{
/** perform my logic here... **/
Thread.Sleep(1000);
return "yes";
}
The error message is
The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
I'm confused. When I use the await keyword, the calling thread will be suspended and wait for task completion. So once await is in use, the method is no longer an async method. Right?
Remark: I know I should put the logic in MyMethod and MyMethodAsync calls MyMethod to achieve what I want.
The entire point of the async keyword is to enable the await keyword.
I collected a number of "why do the keywords work that way?" questions on my blog. The question of "why can't async be inferred by the presence of await?" was answered conclusively by Eric Lippert on his blog. In short, two reasons: backwards compatibility and code readability.
For a huge amount of insight as to how async and await work internally, check out Jon Skeet's EduAsync blog series: msmvps.com/blogs/jon_skeet/archive/tags/Eduasync/default.aspx
This MSDN article also explains it: http://msdn.microsoft.com/en-us/library/vstudio/hh156513.aspx
Basically: a method modified by the async keyword contains at least one await expression or statement. The method runs synchronously until it reaches the first await expression, at which point it is suspended until the awaited task is complete. In the meantime, control is returned to the caller of the method. If the method does not contain an await expression or statement, then it executes synchronously.
Finally, this MSDN article: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx walks through a step-by-step example, about 1/3 of the way down the page:
Related
This question already has answers here:
Why use async and return await, when you can return Task<T> directly?
(9 answers)
Closed 1 year ago.
When writing async functions, usually if you do not explicitly writer await or async your compiler would throw an error or warning. Example of correct syntax below:
public async Task<List<TEntity>> GetEntitiesAsync() =>
await TEntityRepository.GetAllAsync();
Now the following works still, it is async and returns a Task<List>
public Task<List<TEntity>> GetEntitiesAsync() =>
TEntityRepository.GetAllAsync();
Why does the second one still work
Both calls return the same Task, so they are the effectively the same.
In order to use "await" in a method, that method MUST be labeled async. Since the second one doesn't use await, it doesn't need to be labeled async.
That's it.
With that said, it probably isn't a good ideas to do this as there are some pitfalls as described in the article mentioned by #TheGeneral:
https://blog.stephencleary.com/2016/12/eliding-async-await.html
This question already has answers here:
What's the new C# await feature do? [closed]
(5 answers)
Does await create another thread internally before shifting to the same thread as the caller (for UI application)
(2 answers)
Regarding how Async and Await works c#
(7 answers)
What am I doing wrong with async/await? [closed]
(1 answer)
Closed 5 years ago.
I am still struggling to fully understand async/await approach. Can anyone tell me as in topic does await really does Task.Run behind? Sometimes people doing async metod including await but saw sometimes people do Task.Run without async method. What is the the right way?
No, async await is just made to allow code to run whilst something else is blocking, and it doesn't do Task.Run, or start a new thread.
https://blog.stephencleary.com/2013/11/there-is-no-thread.html is a decent explanation of it.
The async operator simply turns on the use of the await operator in a method. The await operator will work on anything which is awaitable. In .NET, Task and Task<T> are some examples of awaitables.
Task.Run returns Task and Task.Run<T> returns Task<T> and as I said they are both awaitable so you can await on them.
You can even write your own awaitable type if you want: You just have to make sure to satisfy the requirements of what is considered an awaitable. An awaitable needs to provide an implementation for GetAwaiter and that's it. Here is an awaitable example:
public struct SimpleInt32Awaitable
{
public SimpleInt32Awaiter GetAwaiter()
{
return new SimpleInt32Awaiter();
}
}
public struct SimpleInt32Awaiter
{
public bool IsCompleted { get { return true; } }
public void OnCompleted(Action continuation)
{
}
public int GetResult()
{
return 5;
}
}
And now you can do this:
// Within some other class
static async void SimpleWaitAsync()
{
SimpleInt32Awaitable awaitable = new SimpleInt32Awaitable();
int result = await awaitable;
}
does await really does Task.Run behind?
Others have already linked to one of Cleary's many excellent blog posts on C# concurrency, There Is No Thread.
No, it doesn't use Task.Run behind the scenes.
await is useful for more than just Task.Run. It's for running code after something has completed. That something could be a computation task created with Task.Run, but it could also be, say, data-retrieval, such as with ReadLineAsync. Task is the class used to model all of those somethings.
Task.Run is used to queue work to run on the thread-pool. This is appropriate when writing CPU-bound code, but you shouldn't use Task.Run when dealing with IO-bound operations. In that case, your asynchronous code (perhaps using async/await) should make use of asynchronous IO methods such as WriteLineAsync and the aforementioned ReadLineAsync.
It's an anti-pattern to use Task.Run to run blocking code on a worker thread. You never want to do that, even if it does, say, unblock your GUI thread.
Sometimes people doing async metod including await but saw sometimes people do Task.Run without async method. What is the the right way?
You can indeed create a Task using Task.Run and just let it run, without using await or ContinueWith. These are called 'fire and forget' tasks. They're rarely a good idea. Unlike when await is used, any exception thrown by that task will be lost.
This is explained by -- you guessed it -- Stephen Cleary, in this StackOverflow answer.
There are cases where you are restricted from using async and await - this is, generally, why you will sometimes see Task.Run used instead - this allows you to utilize async code in a synchronous method.
An example of where this is necessary is when using MVC with Child Actions - the framework does not support async child actions, so you must call async code using Task.Run.
Assume I have a method that has void return type and that I need to await on an operation in this method.
public void someOperation()
{
//dostuff
var res = await someOtherOperation();
//do some other stuff that needs res.
}
When I tried to compile this code I got the error saying someOperation has to be declare async. I don't understand why. I understand why it would if the method had a return value, but not here when it's void. or even in the case when the awaiting operation has no effect on the return value of method.
This has already been asked as a part of this question but I didn't find the answer I was looking for. This guy merely mentions:
The async keyword enables the await keyword. So any method using await
must be marked async.
First of all, I'm not sure what it means that async keyword enables await keyword.
And secondly, restating my question, I'm not sure why it is required?
Asynchronous methods must be marked async. The async and await keywords are paired together, primarily for backwards-compatibility reasons; await was a valid identifier (not a keyword), so when it was added to the language, they also added the async keyword.
Alternatively, they could have gone with a multi-word keyword for await, such as await for. However, the language design team decided to go with the pairing, since it clearly and explicitly marks all async methods - it's easier for both compilers and humans to parse.
I have a blog post on the subject, with links to Eric Lippert's definitive blog post as well as discussions in blog comments, Channel9 forums, MSDN forums, and of course right here on Stack Overflow.
Note that the natural return type of an async method without a result value is Task, not void. void is an unnatural return type for async methods. So your default reaction when seeing the "await operator must be within an async method" error should be to mark it async and change the return type from void to Task:
public async Task someOperationAsync()
{
//dostuff
var res = await someOtherOperationAsync();
//do some other stuff that needs res.
}
This follows one of the best practices in my MSDN article on the subject: avoid async void. async void was allowed by the language designers for event handlers (or code that is logically an event handler, like ICommand.Execute); any other usage is going to cause problems.
I don't understand why.
Because you need to tell the compiler that you're trying to write an async method. That's exactly what the document you're quoting means.
The compiler could infer that from whether or not your method includes any await expressions - but that would mean you could comment out one line of a method and the whole method's behaviour would radically change. (Think about exception handling, for example...)
It also improves readability - it means anyone reading your code knows this is an async method right from the start.
So basically, the answers are:
You need to because the language specification requires you to. The compiler is implementing the language specification.
The language specification requires you to because it reduces the element of surprise.
Because they must work in pair in C#. It is the rule.
The “async” keyword enables the “await” keyword in that method and changes how method results are handled. That’s all the async keyword does! It does not run this method on a thread pool thread, or do any other kind of magic. The async keyword only enables the await keyword (and manages the method results).
I am experimenting with the new async and await keywords. I produced the following asynchronous function:
private async static Task<string> GetStringAsync(string pageAddress)
{
HttpClient client = new HttpClient();
return client.GetStringAsync(pageAddress);
}
I understand that I am returning a Task<String> and can await the result from another method. This method works fine. My question is what happens (under the hood as it were) when I replace the second line of the above function with the following (notice the introduction of the await keyword):
return await client.GetStringAsync(pageAddress);
The function behaves in exactly the same way! Remember the function returns Task<string> not string. Is the await keyword here degenerate? Does the compiler simply strip it from my code?
The answer to this question is too large to post here given your likely current level of understanding. What you should do is start by reading my MSDN article and then Mads' MSDN article; they are a good beginner introduction to the feature and Mads describes how it is implemented. You can find links here:
http://blogs.msdn.com/b/ericlippert/archive/2011/10/03/async-articles.aspx
Then if you are interested in the theory underlying the feature you should start by reading all my articles on continuation passing style:
http://blogs.msdn.com/b/ericlippert/archive/tags/continuation+passing+style/
Start from the bottom. Once you understand the notion of continuation, you can then read my series of articles on how we designed the async feature:
http://blogs.msdn.com/b/ericlippert/archive/tags/async/
As Eric Lippert pointed out, the first version won't compile; you have to remove the async keyword or you'll get a type error.
Here's a useful mental model regarding how the async and await keywords work with the return type:
Any value T returned by an async method is "wrapped" into a Task<T>.
The await keyword (which you can think of as an operator), when applied to a Task<T>, will "unwrap" it, resulting in a value of type T.
Now, that's an extreme simplification; what's actually happening is more complicated. E.g., this simplification skips over how await works with the current SynchronizationContext: in the second example, the method will attempt to return to the original context after the await completes, so you will observe different behavior if that context is busy.
But for the most part, the two examples are almost equivalent. The second one is less efficient due to the async state machine and resuming on the context.
I have an async/await intro that you may find helpful; in that post I try to explain async in a way that is not too complex but also not actually incorrect. :)
Eric's obviously the expert here and his advice is sound, but to answer your specific question:
In the first version, the async keyword on the method is irrelevant and your GetStringAsync method returns the same Task<string> awaitable that's returned by client.GetStringAsync.
In the second version, the async keyword on the method is required because you're using await in the method and the await keyword creates and returns a separate Task<string> awaitable that completes once the awaitable from client.GetStringAsync completes. When that occurs, the await then evaluates to the string that was asynchronously obtained by client.GetStringAsync which is returned as the result of your asynchronous method.
So to the caller of GetStringAsync, they're functionally the same, but the first version is cleaner.
In looking at various C# Async CTP samples I see some async functions that return void, and others that return the non-generic Task. I can see why returning a Task<MyType> is useful to return data to the caller when the async operation completes, but the functions that I've seen that have a return type of Task never return any data. Why not return void?
SLaks and Killercam's answers are good; I thought I'd just add a bit more context.
Your first question is essentially about what methods can be marked async.
A method marked as async can return void, Task or Task<T>. What are the differences between them?
A Task<T> returning async method can be awaited, and when the task completes it will proffer up a T.
A Task returning async method can be awaited, and when the task completes, the continuation of the task is scheduled to run.
A void returning async method cannot be awaited; it is a "fire and forget" method. It does work asynchronously, and you have no way of telling when it is done. This is more than a little bit weird; as SLaks says, normally you would only do that when making an asynchronous event handler. The event fires, the handler executes; no one is going to "await" the task returned by the event handler because event handlers do not return tasks, and even if they did, what code would use the Task for something? It's usually not user code that transfers control to the handler in the first place.
Your second question, in a comment, is essentially about what can be awaited:
What kinds of methods can be awaited? Can a void-returning method be awaited?
No, a void-returning method cannot be awaited. The compiler translates await M() into a call to M().GetAwaiter(), where GetAwaiter might be an instance method or an extension method. The value awaited has to be one for which you can get an awaiter; clearly a void-returning method does not produce a value from which you can get an awaiter.
Task-returning methods can produce awaitable values. We anticipate that third parties will want to create their own implementations of Task-like objects that can be awaited, and you will be able to await them. However, you will not be allowed to declare async methods that return anything but void, Task or Task<T>.
(UPDATE: My last sentence there may be falsified by a future version of C#; there is a proposal to allow return types other than task types for async methods.)
(UPDATE: The feature mentioned above made it in to C# 7.)
In case the caller wants to wait on the task or add a continuation.
In fact, the only reason to return void is if you cannot return Task because you're writing an event handler.
Methods returning Task and Task<T> are composable - meaning that you can await them inside of an async method.
async methods returning void are not composable, but they do have two other important properties:
They can be used as event handlers.
They represent a "top-level" asynchronous operation.
The second point is important when you're dealing with a context that maintains a count of outstanding asynchronous operations.
The ASP.NET context is one such context; if you use async Task methods without awaiting them from an async void method, then the ASP.NET request will be completed too early.
Another context is the AsyncContext I wrote for unit testing (available here) - the AsyncContext.Run method tracks the outstanding operation count and returns when it's zero.
Type Task<T> is the workhorse type of the Task Parallel Library (TPL), it represents the concept of "some work/job that is going to produce a result of type T in the future". The concept of "work that will complete in the future but returns no result" is represented by the non-generic Task type.
Precisely how the result of type T is going to be produced is and implementation detail of a particular task; the work might be farmed out to another process on the local machine, to another thread etc. TPL tasks are typically farmed out to worker threads from a thread pool in the the current process, but that implementation detail is not fundamental to the Task<T> type; rather a Task<T> can represent any high-latency operation that produces a T.
Based on your comment above:
The await expression means "evaluate this expression to obtain an object representing work that will in future produce a result. Sign up the remainder of the current method as the call back associated with the continuation of that task. Once that task is produced and the call back is signed up, immediately return control to my caller". This is opposed/in contrast to a regular method call, which means "remember what you're doing, run this method until it is completely finished and then pick up where you left off, now knowing the result of the method".
Edit: I should cite Eric Lippert's article in October 2011 MSDN Magazine as this was a great help to me in understanding this stuff in the first place.
For loads more infromation and whitepages see here.
I hope this is of some help.