7

出于好奇,我试图在 .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 包Microsoft.Bcl.Async,它不支持 .NET 3.5。

问题:编译代码所需async的最小类型和类型成员集是多少?这个最小集合是否正式记录?如果是这样,在哪里?(请注意,我只对成功编译感兴趣,而不是执行。)


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

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

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

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

  • System.Runtime.CompilerServices.IAsyncStateMachine
  • System.Runtime.CompilerServices.INotifyCompletion(上面的示例代码需要)
  • System.Threading.Tasks.CancellationToken(要求Task
  • System.Threading.Tasks.TaskCreationOptions(要求Task
  • System.Threading.Tasks.Task

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

4

2 回答 2

8

在 C# 编译器方面,您还需要:

我不希望或者实际上会需要 - 我想不出它们会在生成的代码中使用的地方。TaskCreationOptionsCancellationToken

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

源代码不适用于 C# 5 编译器,因为最终版本发生了一些变化,但大多数概念保持不变。

于 2013-07-31T11:57:07.083 回答
2

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

我发现 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在它说的任何地方扔一个{ … }。)

于 2013-08-02T20:47:30.313 回答