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

sta*_*ica 7 c# infrastructure .net-3.5 async-await

出于好奇,我试图在.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();
}
Run Code Online (Sandbox Code Playgroud)

我完全清楚.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有很多成员,但是编译器没有准确报告它需要哪些成员; 它只是报告整体类型.因此,我可能会重现比实际需要更多的类型定义.

Jon*_*eet 8

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

我不希望其中任何一个TaskCreationOptionsCancellationToken实际需要 - 我无法想到它们将在生成的代码中使用的位置.

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

源代码不会对C#编译器5作为工作的东西改了一下的最终版本,但大多数的概念已经保持不变.


sta*_*ica 3

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

\n\n\n\n

我发现 C# 编译器可以接受的最基本的声明如下。

\n\n
namespace System.Threading.Tasks\n{\n    abstract class Task { }\n    abstract class Task<TResult> : Task { }\n}\n\nnamespace System.Runtime.CompilerServices\n{\n    interface INotifyCompletion { }\n    interface ICriticalNotifyCompletion { }\n\n    interface IAsyncStateMachine\n    {\n        void MoveNext();\n        void SetStateMachine(IAsyncStateMachine stateMachine);\n    }\n\n    struct AsyncVoidMethodBuilder\n    {\n        public static AsyncVoidMethodBuilder Create() { \xe2\x80\xa6 }\n        public void Start<TStateMachine>(ref TStateMachine stateMachine)\n            // where TStateMachine : IAsyncStateMachine\n            { \xe2\x80\xa6 }\n        public void SetResult() { \xe2\x80\xa6 }\n        public void SetException(Exception exception) { \xe2\x80\xa6 }\n        public void SetStateMachine(IAsyncStateMachine stateMachine) { \xe2\x80\xa6 }\n        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)\n            // where TAwaiter : INotifyCompletion\n            // where TStateMachine : IAsyncStateMachine\n            { \xe2\x80\xa6 }\n        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)\n            // where TAwaiter : ICriticalNotifyCompletion\n            // where TStateMachine : IAsyncStateMachine\n            { \xe2\x80\xa6 }\n    }\n\n    struct AsyncTaskMethodBuilder\n    {\n        public Task Task { get { \xe2\x80\xa6 } }\n        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)\n            // where TAwaiter : INotifyCompletion\n            // where TStateMachine : IAsyncStateMachine\n            { \xe2\x80\xa6 }\n        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)\n            // where TAwaiter : ICriticalNotifyCompletion\n            // where TStateMachine : IAsyncStateMachine\n            { \xe2\x80\xa6 }\n        public static AsyncTaskMethodBuilder Create() { \xe2\x80\xa6 }\n        public void SetException(Exception exception) { \xe2\x80\xa6 }\n        public void SetResult() { \xe2\x80\xa6 }\n        public void SetStateMachine(IAsyncStateMachine stateMachine) { \xe2\x80\xa6 }\n        public void Start<TStateMachine>(ref TStateMachine stateMachine) \n            // where TStateMachine : IAsyncStateMachine\n            { \xe2\x80\xa6 }\n    }\n\n    struct AsyncTaskMethodBuilder<TResult>\n    {\n        public static AsyncTaskMethodBuilder<TResult> Create() { \xe2\x80\xa6 }\n        public void Start<TStateMachine>(ref TStateMachine stateMachine) \n            // where TStateMachine : IAsyncStateMachine \n            { \xe2\x80\xa6 }\n        public void SetResult(TResult result) { \xe2\x80\xa6 }\n        public void SetException(Exception exception) { \xe2\x80\xa6 }\n        public void SetStateMachine(IAsyncStateMachine stateMachine) { \xe2\x80\xa6 }\n        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)\n            // where TAwaiter : INotifyCompletion\n            // where TStateMachine : IAsyncStateMachine \n            { \xe2\x80\xa6 }\n        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)\n            // where TAwaiter : ICriticalNotifyCompletion\n            // where TStateMachine : IAsyncStateMachine \n            { \xe2\x80\xa6 }\n        public Task<TResult> Task { get { \xe2\x80\xa6 } }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

(我NotImplementedException在它说的地方扔了一个{ \xe2\x80\xa6 }。)

\n