异步/等待限制

时间:2013-11-05 20:39:58

标签: c# async-await

async与方法签名一起使用以及在这些方法中使用带有表达式的await有什么其他限制,如果有的话?到目前为止,我知道标有async的方法只能有以下返回类型之一(可能还有更多?)。

  • void
  • Task
  • Task<TResult>

3 个答案:

答案 0 :(得分:7)

我有intro on my blog你可能会觉得有帮助。

await只要求传递一个“等待”的实例(匹配某个模式,类似于foreach的工作方式)。最常见的等待是任务,但还有其他(例如,Windows Store异步操作)。

必须在使用async的任何方法上使用

awaitasync方法必须返回TaskTask<T>,如果绝对必须,则void

答案 1 :(得分:6)

async修饰符仅适用于返回类型为voidTaskTask<T>的方法。通常, 只能用于包含await运算符的方法。

await运算符可用于 t 的任何类型(来自C#语言规范,7.7.7):

  

t有一个名为GetAwaiter的可访问实例或扩展方法,没有参数,没有类型参数,还有一个返回类型A,以下所有内容都为:

     
      
  • A实现接口System.Runtime.CompilerServices.INotifyCompletion
  •   
  • A具有类型为bool的可访问,可读的实例属性IsCompleted
  •   
  • A具有可访问的实例方法GetResult,没有参数且没有类型   参数
  •   

实际上,这通常意味着您可以在任何awaitTaskTask<T>IAsyncOperation(来自Windows Store API)上使用IAsyncOperation<T>,以及框架中的一些其他选择类型。

答案 2 :(得分:3)

您已经遇到了async方法的主要技术约束。我会提供这个额外的指导:

  1. 声明async方法至少只有await一个操作是没有意义的,因为这种方法等同于常规的同步方法。
  2. 您应该避免编写async void方法。这些仅用于支持编写异步事件处理程序。
  3. 如果您调用 async方法,则应await该方法(或者至少访问任务的IsFaulted状态并检索其Exception如果发生了一次)。如果不这样做,并且该方法中的等待操作之一抛出了您未捕获的异常,则将在终结器线程 1 (错误)上重新抛出该异常。
  4. 你可以await任何具有等待类型的对象,即声明成员的类型:

    TAwaiter GetAwaiter();
    

    TAwaiter是声明以下成员的类型:

    bool IsCompleted { get; }
    TResult GetResult();
    void OnCompleted(Action continuation);  // inherited from INotifyCompletion
    

    IsCompleted属性是自描述的:如果等待操作已经完成,则返回true;否则,它返回false。

    GetResult()方法返回操作的结果,如果操作没有返回类型,则返回void。如果在IsCompletedfalse时被调用,则应该抛出。

    OnCompleted()方法用于注册延续,即在完成操作时调用的代码。该成员实际上应该从INotifyCompletion命名空间中的System.Runtime.CompilerServices继承(所有等待者都应该实现此接口)。


    1 这不再是.NET 4.5中的默认行为,但仍可通过配置更改在客户端计算机上启用它。