2011-08-10 13 views
13

私は非同期CTPを手に入れようとしていますが、コンパイラが非同期戻り型について不満を感じました。他のタイプの問題は何ですか?非同期戻り型がvoid、タスクまたはタスクである必要がある理由<T>

簡単なデモ

static void Main(string[] args) 
{ 
    DoWork(); 
    Console.WriteLine("Returned to main"); 
    Console.Read(); 
} 

// why do I need to return void, Task or Task<T> here? 
// I know I can use something like Task<IEnumerable<string>> 
private static async string[] DoWork() 
{ 
    Console.WriteLine("DoWork started"); 
    return await Task.Factory.StartNew(
     delegate 
     { 
      Thread.Sleep(2000);     
      Console.WriteLine("DoWork done"); 
      return new List<string>(); 
     });   
} 

答えて

11

await [消費]側では柔軟性があります: に正しい方法があれば、どんなタイプでもお待ちしています。

[生産]側のasyncメソッドでは、柔軟性がありません。 にハードコードされているため、タスクタイプ(またはvoid)のみが返されます。 なぜ矛盾?

  1. イテレータは既にこの問題を持っている...

    イテレータ方法(内部「収率」を有するもの) IEnumerableを、またはいずれかのIEnumeratorを返すようにハードコーディングされています。 しかし、 GetEnumerator/MoveNext/Currentメンバーを持つ任意のタイプに対して「foreach」できます。 Asyncはスイートの次の部分です。

  2. タスクは、それがハードコードに良いですので...

    タスクは、将来のよりかろうじてよりあり、将来のようなものです。 未来は言語/プラットフォームの基本的な基本部分です。 言語2がそのような基本的な概念の複数のコピーを持つ理由はありません。 概念。 1つで十分です。先物を扱うために、キーワードを 言語に追加することも非常に重要です。 とにかく、誰かが将来のようなもの、またはタスクのより豊かな概念を持っている場合は、 タスクまたはFuncからビルドすることができます。 (私たちのタスクはすでに実行されています。F# asyncsやIObservableのような、 "冷たい"ものを作成したい場合は、あなたがそれを伝えるまで起動しないものです - タスクの外に出る)。

  3. さらに微妙な

    は、この関数を定義します。

    void f<T>(Func<Task<T>> f) 
    

    そして、それを呼び出す:

    f(() => 1 + await t) 
    

    私たちは、この中でそのT = int型を推測できるようにしたいのですが場合。 コンパイラが "f"に渡すラムダがタイプ Task<int>であることをハードコーディングしていない限り、このような推論は不可能です。

出典:Technical intro to the Async CTP

6

Task<TResult>は「未来」であるので - に沿って、後に来るということだ値。 string[]はあなたが今持っているものです。

同様に、Taskは、将来、いつか(正常にまたはエラーとともに)完了する操作です。

voidは特殊なケースです。 Async CTPのトップレベルの操作を表します。

なぜTaskが自動的に推論されないのか疑問に思うなら、これは考慮されましたが、Async CTPチームによって拒否されました。彼らの論理的根拠はhereであり、this threadもそれをカバーしています。