2013-07-31 65 views
6

出於好奇,我試圖得到一些簡單的async/await代碼在.NET 3.5客戶端配置文件進行編譯:編譯`async`代碼所需的最小類型集是多少?

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不支持這種語言特性,如在此編譯錯誤表示:

Cannot find all types required by the async modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?

我也知道NuGet package Microsoft.Bcl.Async,不具有對.NET 3.5的支持。

問題:是什麼類型的需要&類型成員async代碼編譯最小集合?正式記錄了這個最小集合嗎?如果是的話,在哪裏? (請注意,我只是在成功編譯,執行不感興趣。)


到目前爲止,我已經得到了什麼:

我一直試圖找到這組最小的類型實驗中,這似乎因爲需要編譯器報告是可能的,但缺少的類型逐一:

Predefined type System.Runtime.CompilerServices.IAsyncStateMachine is not defined or imported.

定義根據MSDN參考頁報告的類型,然後導致所報告的下一個缺少類型。我迄今爲止:

  • System.Runtime.CompilerServices.IAsyncStateMachine
  • System.Runtime.CompilerServices.INotifyCompletion
  • System.Threading.Tasks.CancellationToken(由Task必需)
  • System.Threading.Tasks.TaskCreationOptions(由Task必需)
  • System.Threading.Tasks.Task
(由上面的示例代碼所需)

在這一點上我因爲Task有很多成員,但是編譯器並不準確報告它需要的成員;它只是報告整個類型。因此,我可能會重現更多的類型定義,而不是實際需要的。

回答

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無論它說{ … }。)

8

在C#編譯器來說,你還需要:

我不會預期,要麼TaskCreationOptionsCancellationToken實際上需要 - 我不認爲他們會在生成的代碼中使用。

從根本上說,你確實需要整個TPL支持它才能正常工作 - 只需要它編譯不會爲你做。如果你只是對好奇心感興趣,那是另外一回事。您可能對我的Eduasync博客系列感興趣,這是一個原始版本,讓CTP版本的編譯器在沒有AsyncCtpLibrary.dll程序集(針對.NET 4.0)的情況下工作 - 主要提供所有相關類型。

source code對於C#5編譯器不起作用,因爲最終版本發生了一些變化,但大多數概念都保持不變。

+0

感謝。你是否自己發現了列表中的類型,或者你是否從官方文檔中獲取了列表? - 也感謝Eduasync鏈接,我已經開始閱讀這些博客文章。 – stakx

+1

@stakx:那麼我最初建立了列表,因爲我沿着它走了並實現了Eduasync的一些部分 - 但現在我回頭看看編譯器在生成的代碼中使用的類型。 –

相關問題