2013-07-31 4 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

В этот момент я topside, так как 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# компилятор, вам также необходимо:

Я бы не ожидать что либо TaskCreationOptions или CancellationToken бы на самом деле потребуется - я не могу думать, где они будут использоваться в сгенерированном коде.

В принципе, вам действительно нужна вся поддержка TPL для его работы - просто наличие компиляции не собирается делать это за вас. Если вас интересует только любопытство, это другое дело. Вас может заинтересовать мой блог Eduasync, который был грубой версией получения CTP-релиза компилятора для работы без сборки AsyncCtpLibrary.dll (против .NET 4.0) - в основном поставляя все соответствующие типы.

source code не будет работать против компилятора C# 5, поскольку некоторые вещи немного изменились для окончательной версии, но большинство концепций остались прежними.

+0

Спасибо. Вы сами узнали о типах в своем списке, или вы взяли список из официальной документации? - Спасибо также за ссылку Eduasync, я уже начал читать эти статьи в блоге. – stakx

+1

@stakx: Ну, я изначально создал список, когда я пошел и реализовал бит Eduasync, но теперь я оглядываюсь на типы, которые, как я знаю, используют компилятор в сгенерированном коде. –