【问题标题】:What is the minimum set of types required to compile `async` code?编译“异步”代码所需的最少类型集是什么?
【发布时间】:2013-07-31 11:51:25
【问题描述】:

出于好奇,我正在尝试获取一些简单的async/await 代码以在 .NET 3.5 客户端配置文件下编译:

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 有很多成员,但编译器并没有准确报告它需要哪些成员;它只是报告整个类型。因此,我可能会复制比实际需要更多的类型定义。

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 谢谢。您是自己了解列表中的类型,还是从官方文档中获取列表? -- 也感谢 Eduasync 链接,我已经开始阅读这些博客文章了。
    • @stakx:嗯,我最初建立了这个列表,并实现了一些 Eduasync - 但现在我回顾了我知道编译器在生成的代码中使用的类型。
    【解决方案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。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-17
      • 1970-01-01
      • 2017-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-04
      相关资源
      最近更新 更多