I'm looking at the MSDN documentation and it says
Async methods have three possible return types:
Task<TResult>
,Task
, andvoid
.
https://msdn.microsoft.com/en-us/library/mt674893.aspx
However, I remember reading somewhere else that it's possible to write to await
custom awaiters. How can I reconcile these 2 facts?
await
supports any kind of "awaitable", which are object instances that follow a certain pattern ( GetAwaiter
, etc).
async
generates a state machine which only knows how to create Task
/ Task<T>
awaitables (or return void
).
So, you can create your own custom awaitable object and return that, but you have to do it explicitly. You can't use async
to do it.
The compiler team is currently looking at adding ValueTask
support to async
. This would allow you to use "async method builders" that would follow a pattern. Then you'd be able to use async
as well as await
to operate on any kind of "tasklike" type. Unfortunately, it would still not allow async
methods to return interface types, though - changes in other parts of the language are necessary for that.
The native classes shipped with .NET (specifically TaskAwaiter) only support Task
, Task<T>
and void
as awaitable, thus this is all MSDN tells you about. However, you can write custom awaiters that allow awaiting other types.
According to https://weblogs.asp.net/dixin/understanding-c-sharp-async-await-2-awaitable-awaiter-pattern , an object is awaitable if:
- It has a GetAwaiter() method (instance method or extension method);
- Its GetAwaiter() method returns an awaiter. An object is an awaiter if:
- It implements INotifyCompletion or ICriticalNotifyCompletion interface;
- It has an IsCompleted, which has a getter and returns a Boolean;
- it has a GetResult() method, which returns void, or a result.
The first line of the link you provided reads as follows:
Updated: July 20, 2015
So this is a bit dated. With that said, originally async
methods did only have Task<TResult>
, Task
, and void
as valid returns types. According to the C# Language Specification the following is stated:
10.15 Async Functions
The return-type of an async method must be either void or a task type.
With the introduction of UWP , you get four more built-in types:
IAsyncAction
IAsyncActionWithProgress<TProgress>
IAsyncOperation<TResult>
IAsyncOperationWithProgress<TResult, TProgress>
These are considered "async types" and you are allowed to use the async
and await
keywords on them as you'd expect.
More from the spec:
The return-type of an async method must be either void or a task type . The task types are
System.Threading.Tasks.Task
and types constructed fromSystem.Threading.Tasks.Task<T>
. For the sake of brevity, in this chapter these types are referenced asTask
andTask<T>
, respectively. An async method returning a task type is said to be task-returning.The exact definition of the task types is implementation defined, but from the language's point of view a task type is in one of the states incomplete, succeeded or faulted. A faulted task records a pertinent exception. A succeeded
Task<T>
records a result of typeT
. Task types are awaitable, and can therefore be the operands of await expressions
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.