2011-06-02 90 views
1

我發現在C#中調用TaskEx.Delay與異步框架CTP當某種問題的異步框架TaskEx.Delay問題

public async Task<string> TestAsync() { 
    return await TaskEx.RunEx<string>(async() => { //in real app this is time consuming code so this line is so complex 
      await TaskEx.Delay(1000); 
      return "test; 
     }); 
} 

public async void Test { 
    var count = 0; 
    while(count < 100) { 
     var val = await TestAsync(); 
     Console.WriteLine(val); // in real app this line adds elements to observable collection binded to ListBox 
     count++; 
    } 
} 

在控制檯上輸出出現一次主要是(有時是兩個三次)但不是我所期望的100倍。

編輯:

它不控制檯應用程序(上面的代碼被簡化)它是WP7應用程序。沒有使用延遲它工作正常。

+1

這不是您正在運行的實際代碼 - 您已經在等待非異步方法。如果你能想出一個簡短但完整的程序,那真的會有所幫助。目前我無法訪問編譯器,但通過一個完整的應用程序,我至少可以更多地診斷正在發生的事情。 – 2011-06-02 17:15:59

+0

如果您認爲TaskEx.Delay有問題,請嘗試在控制檯應用程序中顯示它。 – 2011-06-02 21:13:19

+0

我很確定 - 從Microsoft Visual Studio異步CTP包打開示例項目(C#Windows Phone)Netflix。在MainPage.xaml.cs中的LoadMoviesAsync中添加等待TaskEd.Delay(1000),在78行右下方的imageCount + = movies.Length;並將pageCount更改爲2以更好地查看結果。啓動應用程序,在年份框中輸入2000,然後上下移動列表中的項目。經過一段時間後,物品將停止加載,但仍有數百個物品剩下。刪除延遲,沒有問題! – awattar 2011-06-02 22:10:57

回答

2

這可能是由於您正在控制檯應用程序中運行,而不是Windows應用程序。

由於沒有同步上下文,因此異步在控制檯應用程序中的行爲與在Windows窗體,WPF或WCF應用程序中的行爲不同。因此,await會回到一個線程池線程,並且實際上不會「等待」執行。

如果您在WPF或Windows窗體應用程序中運行它,它將按預期運行。


在附註中,您的方法過於複雜。你可以這樣做:

public async Task<string> TestAsync() { 
    await TaskEx.Delay(1000); 
    return "test"; 
} 

這將,有效,工作方式與以前的方法相同,但用少得多的開銷(和簡單得多)。

+0

我認爲說「異步在控制檯應用程序中無法按預期工作」是誤導性的,因爲這顯然取決於您的期望。異步的工作原理與*我希望它在控制檯應用程序中一樣,這是我測試大部分內容的地方:)示例代碼當前不完整,但可以在控制檯應用程序中以合理方式輕鬆運行。 – 2011-06-02 17:22:17

+0

@Jon:控制檯模式應用程序中的異步和等待行爲與Windows窗體,WPF,WCF等應用程序(當然,除非安裝自定義同步上下文)顯着不同。由於線程同步和許多問題發揮作用,所發生的事情的正常指導會發生顯着變化。是的,使用異步編寫合理的控制檯模式應用程序是完全可能的,但它需要您真正關注自己在做什麼。 – 2011-06-02 17:26:44

+0

@Jon:更好的措辭? :) – 2011-06-02 17:30:49

2

這是因爲方法Test確實是一個異步方法。 C#編譯器只是讓你通過void返回類型來隱藏它。所以,如果你的主要方法如下所示

public static void Main() { 
    Test(); 
} 

那就不是實際運行Test,並等待它完全完成。這實際上是安排Test運行,它的完成將在未來某個時刻發生。因此,您看到不同的輸出是有道理的,因爲它與時間有關。