2011-08-10 55 views
13

我想讓我的手髒異步CTP和我注意到,編譯器抱怨異步返回類型。其他類型的問題是什麼?爲什麼返回類型的異步必須是無效的,任務或任務<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方法[製作]方面,我們缺乏靈活性:我們硬編碼爲 ,只返回Task類型(或void)。 爲什麼不一致?

  1. 迭代器已經具備了這種行爲...

    的迭代方法(一個具有「產量」裏面)是硬編碼返回要麼 的IEnumerable或IEnumerator的。 但是,您可以對任何具有GetEnumerator/MoveNext/Current成員的類型進行「foreach」。 所以Async只是跟隨套件。

  2. 任務就像是一個未來,所以這是很好的硬編碼...

    任務是僅比未來更。 未來是語言/平臺的基本基礎部分。 沒有理由說一種語言有兩個這樣的基本概念的多個副本。一個就足夠了。這是非常基礎的,你甚至可以添加關鍵字到 語言來處理期貨。 無論如何,如果有一個人的未來性的東西,或任務的更豐富的內涵,那麼他們可以 打造出來工作或FUNC。菜單的。 (我們的任務已經在運行。如果你想建立的東西,就是「冷」,像F# 異步操作或類似的IObservable,一個不啓動,直到你告訴它 - 那麼你應該 打造出來一個函數功能,而不是出任務)。

  3. 進一步微妙之處

    定義這個功能:

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

    並調用它:

    f(() => 1 + await t) 
    

    我們希望能夠推斷T = INT在此案件。這種推斷是不可能的,除非 編譯器有硬編碼的知識,它傳遞給「f」的lambda具有類型 Task<int>

來源:Technical intro to the Async CTP

6

因爲Task<TResult>是一個「未來」 - 這將在稍後到來沿着價值。 A string[]是你現在的東西。

同樣,Task是一個將在將來某個時間完成(成功或有錯誤)的操作。

void是一種特殊情況;它代表了Async CTP中的頂級操作。

如果您想知道爲什麼Task不是自動推斷出來的,那麼可以認爲這是由Async CTP團隊拒絕的。他們的理由是here,而this thread也涵蓋了它。

相關問題