将async
与方法签名一起使用以及在这些方法中使用带有表达式的await
有什么其他限制,如果有的话?到目前为止,我知道标有async
的方法只能有以下返回类型之一(可能还有更多?)。
void
Task
Task<TResult>
答案 0 :(得分:7)
我有intro on my blog你可能会觉得有帮助。
await
只要求传递一个“等待”的实例(匹配某个模式,类似于foreach
的工作方式)。最常见的等待是任务,但还有其他(例如,Windows Store异步操作)。
async
的任何方法上使用 await
。 async
方法必须返回Task
或Task<T>
,如果绝对必须,则void
。
答案 1 :(得分:6)
async
修饰符仅适用于返回类型为void
,Task
或Task<T>
的方法。通常, 只能用于包含await
运算符的方法。
await
运算符可用于 t 的任何类型(来自C#语言规范,7.7.7):
t有一个名为GetAwaiter的可访问实例或扩展方法,没有参数,没有类型参数,还有一个返回类型A,以下所有内容都为:
- A实现接口System.Runtime.CompilerServices.INotifyCompletion
- A具有类型为bool的可访问,可读的实例属性IsCompleted
- A具有可访问的实例方法GetResult,没有参数且没有类型 参数
实际上,这通常意味着您可以在任何await
,Task
,Task<T>
,IAsyncOperation
(来自Windows Store API)上使用IAsyncOperation<T>
,以及框架中的一些其他选择类型。
答案 2 :(得分:3)
您已经遇到了async
方法的主要技术约束。我会提供这个额外的指导:
async
方法至少只有await
一个操作是没有意义的,因为这种方法等同于常规的同步方法。async void
方法。这些仅用于支持编写异步事件处理程序。async
方法,则应await
该方法(或者至少访问任务的IsFaulted
状态并检索其Exception
如果发生了一次)。如果不这样做,并且该方法中的等待操作之一抛出了您未捕获的异常,则将在终结器线程 1 (错误)上重新抛出该异常。你可以await
任何具有等待类型的对象,即声明成员的类型:
TAwaiter GetAwaiter();
TAwaiter
是声明以下成员的类型:
bool IsCompleted { get; }
TResult GetResult();
void OnCompleted(Action continuation); // inherited from INotifyCompletion
IsCompleted
属性是自描述的:如果等待操作已经完成,则返回true
;否则,它返回false。
GetResult()
方法返回操作的结果,如果操作没有返回类型,则返回void
。如果在IsCompleted
为false
时被调用,则应该抛出。
OnCompleted()
方法用于注册延续,即在完成操作时调用的代码。该成员实际上应该从INotifyCompletion
命名空间中的System.Runtime.CompilerServices
继承(所有等待者都应该实现此接口)。
1 这不再是.NET 4.5中的默认行为,但仍可通过配置更改在客户端计算机上启用它。