2013-07-31 15 views
6

Aus Neugier, ich versuche, einige einfache async/await-Code zu erhalten unter Profil .NET 3.5 Client zu kompilieren:Was ist der Mindestsatz von Typen, die zum Kompilieren von Async-Code erforderlich sind?

async void AwaitFoo() 
{ 
    await new Foo(); 
} 

class Foo 
{ 
    public IFooAwaiter GetAwaiter() { … } 
} 

interface IFooAwaiter : System.Runtime.CompilerServices.INotifyCompletion 
{ 
    bool IsCompleted { get; } 
    void GetResult(); 
} 

Ich weiß wohl, dass ich .NET 3.5 nicht diese Sprache-Funktion nicht unterstützt, wie sie durch diese Kompilierungsfehler ausgedrückt:

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

ich bin mir auch bewusst der NuGet package Microsoft.Bcl.Async, die keine Unterstützung für .NET 3.5 hat.

Frage: Was ist der Mindestsatz von Typen & Typ Mitglieder für async Code erforderlich zu kompilieren? Ist dieser minimale Satz offiziell dokumentiert? und wenn ja, wo? (Beachten Sie, dass ich bei der erfolgreichen Compilation nur daran interessiert bin, nicht die Ausführung.)


Was ich bisher habe:

Ich habe versucht, diese minimale Menge von Arten zu finden, indem Experiment, das seit den Compiler Berichten erforderlich, aber fehlenden Typen einzeln möglich zu sein scheint:

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

definieren berichtete Typen gemäß MSDN Referenzseite führen dann zu dem nächsten fehlenden Typ wird berichtet. Ich habe bisher:

  • System.Runtime.CompilerServices.IAsyncStateMachine
  • System.Runtime.CompilerServices.INotifyCompletion (erforderlich durch den Beispielcode oben)
  • System.Threading.Tasks.CancellationToken (wird von Task)
  • System.Threading.Tasks.TaskCreationOptions (erforderlich durch Task)
  • System.Threading.Tasks.Task

An diesem Punkt s getoppt, da Task viele Mitglieder hat, aber der Compiler nicht genau angibt, welche Mitglieder es benötigt; es meldet nur den Typ als Ganzes. Ich könnte daher viel mehr von der Typdefinition reproduzieren als das, was tatsächlich benötigt wird.

Antwort

2

Ich habe durch das Experiment festgestellt, dass die folgenden Arten ausreichend sind, um den C# 5 Compiler Prozess grundlegenden async/await Code zu machen (auch wenn Targeting .NET Framework Version 2!):

Die minimalste Erklärungen für diese, die ich gefunden habe, um die als akzeptabel C# -Compiler folgen unten.

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 { … } } 
    } 
} 

(Ich warf einen NotImplementedException wo immer es { … } sagt.)

8

In Bezug auf den C# -Compiler, müssen Sie auch:

Ich würde nicht erwarten, dass entweder TaskCreationOptions oder CancellationToken würde tatsächlich erforderlich sein - ich kann nicht glauben, wo sie in dem generierten Code verwendet werden würden.

Grundsätzlich benötigen Sie wirklich die gesamte TPL-Unterstützung, damit es funktioniert - einfach kompilieren wird es nicht für Sie tun. Wenn Sie nur aus Neugier interessiert sind, ist das eine andere Sache. Sie könnten an meiner Eduasync Blogserie interessiert sein, die eine grobe Version war, die CTP-Version des Compilers ohne die AsyncCtpLibrary.dll Assembly (gegen .NET 4.0) zu bekommen - im Grunde alle relevanten Typen liefernd.

Die source code wird nicht gegen den C# 5-Compiler arbeiten, da sich die Dinge ein wenig für die endgültige Version geändert haben, aber die meisten Konzepte sind gleich geblieben.

+0

Dank. Haben Sie selbst von den Typen in Ihrer Liste erfahren, oder haben Sie die Liste aus der offiziellen Dokumentation genommen? - Danke auch für den Eduasync-Link, ich habe schon angefangen, diese Blogartikel zu lesen. – stakx

+1

@stakx: Nun, ich habe die Liste anfangs aufgebaut, als ich mit Eduasync gearbeitet habe - aber jetzt schaue ich auf die Typen zurück, von denen ich weiß, dass sie vom Compiler im generierten Code verwendet werden. –