编译`async`代码所需的最小类型是什么?

时间:2013-07-31 11:51:26

标签: c# .net-3.5 async-await infrastructure

出于好奇,我试图在.NET 3.5 Client Profile下编译一些简单的async / await代码:

async void AwaitFoo()
{
    await new Foo();
}

class Foo
{
    public IFooAwaiter GetAwaiter() { … }
}

interface IFooAwaiter : System.Runtime.CompilerServices.INotifyCompletion
{
    bool IsCompleted { get; }
    void GetResult();
}

我完全清楚.NET 3.5不支持此语言功能,如此编译错误所表达的那样:

  

无法找到async修饰符所需的所有类型。您是否定位错误的框架版本,或缺少对程序集的引用?

我也知道NuGet package Microsoft.Bcl.Async,它不支持.NET 3.5。

问题 什么是最小类型&输入async 代码编译所需的成员?这个最小集是否正式记录;如果是的话,在哪里? (请注意,我只对成功编译感兴趣,而不是执行。)


到目前为止我得到了什么:

我一直试图通过实验找到这个最小的类型集,这似乎是可能的,因为编译器需要报告,但是逐个丢失类型:

  

未定义或导入预定义类型System.Runtime.CompilerServices.IAsyncStateMachine

根据MSDN参考页面定义报告的类型,然后导致报告下一个丢失的类型。我到目前为止:

  • System.Runtime.CompilerServices.IAsyncStateMachine
  • System.Runtime.CompilerServices.INotifyCompletion(上述示例代码要求)
  • System.Threading.Tasks.CancellationTokenTask要求)
  • System.Threading.Tasks.TaskCreationOptionsTask要求)
  • System.Threading.Tasks.Task

此时我停了下来,因为Task有很多成员,但编译器并没有准确报告它需要哪些成员;它只是报告整体类型。因此,我可能会重现比实际需要更多的类型定义。

2 个答案:

答案 0 :(得分:8)

就C#编译器而言,您还需要:

我不会期望实际上需要TaskCreationOptionsCancellationToken - 我无法想到它们会在生成的代码中用于何处。< / p>

从根本上说,你真的需要整个TPL支持才能工作 - 只需要编译就不会为你做这件事。如果你只是为了好奇而对此感兴趣,那就是另一回事了。您可能对我的Eduasync博客系列感兴趣,这是一个粗略的版本,让编译器的CTP版本在没有AsyncCtpLibrary.dll程序集(针对.NET 4.0)的情况下工作 - 基本上提供所有相关类型

source code对C#5编译器不起作用,因为最终版本的内容发生了一些变化,但大多数概念保持不变。

答案 1 :(得分:2)

我已经通过实验确定以下类型足以使C#5编译器处理基本的async / await代码(即使面向.NET Framework版本2!): / p>

我发现C#编译器可以接受的最小的声明如下所示。

namespace System.Threading.Tasks
{
    abstract class Task { }
    abstract class Task<TResult> : Task { }
}

namespace System.Runtime.CompilerServices
{
    interface INotifyCompletion { }
    interface ICriticalNotifyCompletion { }

    interface IAsyncStateMachine
    {
        void MoveNext();
        void SetStateMachine(IAsyncStateMachine stateMachine);
    }

    struct AsyncVoidMethodBuilder
    {
        public static AsyncVoidMethodBuilder Create() { … }
        public void Start<TStateMachine>(ref TStateMachine stateMachine)
            // where TStateMachine : IAsyncStateMachine
            { … }
        public void SetResult() { … }
        public void SetException(Exception exception) { … }
        public void SetStateMachine(IAsyncStateMachine stateMachine) { … }
        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
            // where TAwaiter : INotifyCompletion
            // where TStateMachine : IAsyncStateMachine
            { … }
        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
            // where TAwaiter : ICriticalNotifyCompletion
            // where TStateMachine : IAsyncStateMachine
            { … }
    }

    struct AsyncTaskMethodBuilder
    {
        public Task Task { get { … } }
        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
            // where TAwaiter : INotifyCompletion
            // where TStateMachine : IAsyncStateMachine
            { … }
        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
            // where TAwaiter : ICriticalNotifyCompletion
            // where TStateMachine : IAsyncStateMachine
            { … }
        public static AsyncTaskMethodBuilder Create() { … }
        public void SetException(Exception exception) { … }
        public void SetResult() { … }
        public void SetStateMachine(IAsyncStateMachine stateMachine) { … }
        public void Start<TStateMachine>(ref TStateMachine stateMachine) 
            // where TStateMachine : IAsyncStateMachine
            { … }
    }

    struct AsyncTaskMethodBuilder<TResult>
    {
        public static AsyncTaskMethodBuilder<TResult> Create() { … }
        public void Start<TStateMachine>(ref TStateMachine stateMachine) 
            // where TStateMachine : IAsyncStateMachine 
            { … }
        public void SetResult(TResult result) { … }
        public void SetException(Exception exception) { … }
        public void SetStateMachine(IAsyncStateMachine stateMachine) { … }
        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
            // where TAwaiter : INotifyCompletion
            // where TStateMachine : IAsyncStateMachine 
            { … }
        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
            // where TAwaiter : ICriticalNotifyCompletion
            // where TStateMachine : IAsyncStateMachine 
            { … }
        public Task<TResult> Task { get { … } }
    }
}

(我在NotImplementedException所说的任何地方抛出{ … }。)