As far as I know WebRequest.GetResponseAsync() can be awaited and is asynchonous.
But when I look at its source code at https://referencesource.microsoft.com/#System/net/System/Net/WebRequest.cs,99a2a9c8ebc067dc
it isn't defined with the "async" keyword.
I thought you cannot await a method that is not defined as "async"?
I thought you cannot await a method that is not defined as "async"?
This is a kind of "shorthand" way of thinking about it that can be useful while initially learning async, but falls apart when you gain more knowledge about async/await. There are two concepts that are not quite right in this sentence.
First, code cannot await a method. What actually happens is that the method is called, exactly like any other method. That method returns a value - an awaitable type - and it is that return value that is actually awaited. It's common for us to talk about "awaiting a method", but that's just shorthand for "calling a method and awaiting its return value", which is more accurate but too awkward for most conversation.
Second, async is just one way to create an awaitable return value (which can then be awaited). There are several other ways as well. For example, Task<T>.Factory.FromAsync is commonly used if you have an API that uses the older APM asynchronous pattern, and you want to use it with await. In that case, you would normally write wrapper methods that return Task<T> and are implemented using Task<T>.Factory.FromAsync (without async). Another common approach is to use TaskCompletionSource<T>, which can create a Task<T> around any kind of logical "future event".
To put it another way, async is an implementation detail. This concept is further enforced by the fact that interface methods can be declared as returning Task and awaited, but only method implementations can be declared with async.
Related
I'm working on some code which builds a buffer in memory and then empties it into a TextWriter when the buffer fills up. Most of the time, the character will go straight into the buffer (synchronously) but occasionally (once every 4kb) I need to call TextWriter.WriteAsync.
In the System.Threading.Tasks.Extensions package there only appears to be a ValueTask<T> struct, and no non-generic ValueTask (without a type parameter). Why is there no ValueTask, and what should I do if I need to convert a method returning a non-generic Task (that is, the async equivalent of a void method) to ValueTask?
Shot in the dark, but I think it's because Task.CompletedTask is sufficient for most non-generic cases.
One way to think of ValueTask<T> is as a union of Task<T> and T (for asynchronous and synchronous cases respectively). Accordingly a non-generic ValueTask would be a union of Task and... nothing, so just a Task.
I can't think of a case where a non-generic ValueTask would be practically different than caching an already completed Task (which is what Task.CompletedTask is), though I'd love to learn about any.
Based on this article, you can change any asynchronous method directly from Task to ValueTask, but you must beware of its usage patterns mentioned in the article; specifically:
Awaiting the instance multiple times.
Calling AsTask multiple times.
Using more than one of these techniques to consume the instance.
And if you need to get the result back as a Task / Task<TResult>, you should use .AsTask().
The CQS-principle (https://en.wikipedia.org/wiki/Command%E2%80%93query_separation) states that a command should return void.
The recommendation for async methods is to never return void (https://msdn.microsoft.com/en-us/magazine/jj991977.aspx), but instead returning a Task.
So, if I write an async command, will that inevitably break the CQS-principle?
When dealing with async Task represents void and Task<T> represents "a result". So no, it does not violate CQS you just need to think of Task as void.
At the level of considering what you want to know (a query) or do (a command) then Task<T> gives you data and hence is correct for a query and Task does not and hence is correct for a command. ("return void" is the language-specific way for some langauges to express "do not return data").
At the level below that, in which you are considering the mechanism by which asynchronous operations are managed, then you always want to have information about the state of the asynchronous operation and so always want some sort of task object. That is not the level to consider command-query separation.
Comparably, if a .NET method called into a COM method it would be calling into code that always returned a value indicating success or failure. That is just an implementation detail of how exception-handling happens in that particular technology. It's either vital or irrelevant to think about this depending on the level you are working at. Task is an implementation detail of how task-based asynchronous programming works. It's either vital or irrelevant to think about this depending on the level you are working at.
The level at which you need to think about "is this a command or a query", Task is an implementation-detail about how you get void.
From the article you are linking:
When converting from synchronous to asynchronous code, any method
returning a type T becomes an async method returning Task<T>, and any
method returning void becomes an async method returning Task.
Therefore returning Task (not Task<T>) translates to having a method returning void.
I'm looking at some code written a while back that is making me very nervous. The general shape of the methods in questions is like this;
public Task Foo(...){
SyncMethod();
SyncMethod();
...
return AsyncMethod();
}
I realize I can just mark the method async and do an await on the last call, but...do I have to? Is this safe to use as is? The sync methods that are called before the last async method do not have asynchronous alternatives and the Foo method does not care about the result of the AsyncMethod, so it looks like it's ok to just return the awaitable to the caller and let the caller deal with it.
Also, FWIW, the code in question might be called from a thread that's running with an active ASP.NET context, so I'm getting that tingling feeling in my brain that there's some invisible evil that I'm not seeing here?
I realize I can just mark the method async and do an await on the last call, but...do I have to?
Actually, if you did this, the only change that it would have is that exceptions thrown by either of those synchronous methods would be wrapped into the returned Task, while in the current implementation the method would throw without ever successfully returning a Task. The actual effect of what work is done synchronously and what work is done asynchronously is entirely unaffected.
Having said that, both of the options you've mentioned are worrisome. Here you have a method that appears to be asynchronous, meaning someone calling it expects it to return more or less right away, but in reality the method will run synchronously for some amount of time.
If your two synchronous methods are really fast and as a result, you're confident that this very small amount of synchronous work won't be noticeable to any of your callers, then that's fine. If, however, that work will (even potentially) take a non-trivial amount of time to solve, then you have a problem on your hands.
Having actually asynchronous alternatives for those methods would be best, but as a last resort, until you have a better option, often the best you can manage to do is to await Task.Run(() => SyncMethod()); for those methods (which of course means the method now needs to be marked as async).
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).
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.