2012-04-07 50 views
0

我正在用異步CTP進行一些探測,但由於GUI被阻塞,我沒有得到好的結果。異步CTP:我做錯了,GUI被阻止

我有一個WPF應用程序的按鈕和文本框的日誌。然後,我有這樣的代碼:

private async void btnAsync01_Click(object sender, RoutedEventArgs e) 
     { 
      UpdateTxtLog("Enter in Button Async01: " + System.DateTime.Now); 
      await metodo01Async(); 
      UpdateTxtLog("Exit button Async01: " + System.DateTime.Now); 
     } 

private async Task slowMethodAsync() 
     { 
      UpdateTxtLog("Enter in slowMethod: " + System.DateTime.Now); 
      Thread.Sleep(5000); 
      UpdateTxtLog("Exit slowMethod: " + System.DateTime.Now); 
     } 

如果我沒有錯,設定爲「同步」(在這種情況下,單擊事件),它讓該方法使用的await,給點返回到執行該方法的方法它調用實​​際的方法,然後執行返回到GUI。

所以在GUI中,我單擊按鈕,然後在clickMethod的click事件中等待,我如何使用slowMethod等待控件返回到GUI,然後GUI不應該被阻止。但是,圖形用戶界面被阻止,txtLog不顯示任何信息,直到slowMethod完成。

這是因爲slowMethod在與GUI相同的線程中執行嗎?如果我錯了,使用異步通常使用與調用await方法的方法相同的線程,但我認爲異步的原因可以避免這種情況。

我該如何模擬一個沒有thread.Sleep的slowMethod?也許這就是問題所在,因爲在slowMethod中,我睡眠線程,而slowMethod的線程與GUI相同。

這讓我覺得總是推薦在其他線程中執行異步方法的代碼?如果這是正確的,如果我還需要使用任務來阻止主線程,那麼使用異步的意義是什麼?

何時使用異步和何時使用任務?

對於這個探頭,我下面這個網站的例子:http://www.codeproject.com/Articles/127291/C-5-0-vNext-New-Asynchronous-Pattern

在這個例子中,它被用來作爲client.DownloadStringTaskAsync slowMethod,但對我來說,而是採用了Web客戶端,我用一個虛擬的方法,用睡眠模擬slowMethod。我認爲這是唯一的區別。

謝謝。 Daimroc。

回答

2

使用await TaskEx.Delay(5000)模擬等待,其執行異步睡眠/延遲。

您可能還想了解更多async/await。有幾個很好的Channel9視頻; Stephen Toub,Eric Lippert和許多其他微軟博客都有出色的概述。 Jon Skeet的「eduasync」博客系列也非常適合真的走得更深。和其他許多人一樣,我寫了an async intro on my own blog

這裏的asyncawait到底是如何工作,概括地說:

  • async關鍵字僅啓用await關鍵字。就這些。它不是而是在後臺線程上運行該方法。
  • await只有在其「awaiter」未完成時纔會異步執行。

所以在你的情況下,btnAsync01_ClickslowMethodAsync都運行在UI線程上。 slowMethodAsync將同步運行(執行Thread.Sleep),然後返回到btnAsync01_Click,等待已完成的任務。由於該任務已完成,因此btnAsync01_Click只是繼續執行而不會屈服於UI消息循環。

如果用await TaskEx.Delay替換Thread.Sleep,然後btnAsync01_Click將開始在UI線程上運行,並調用slowMethodAsync(也UI線程上運行)。當slowMethodAsyncawait是延遲(未完成)時,它將返回一個不完整的任務到btnAsync01_ClickbtnAsync01_Clickawait該任務(未完成),並將返回到UI循環。

當延遲到期時,它將完成,並且slowMethodAsync將恢復(在UI線程上)。當slowMethodAsync完成時,其返回的任務將完成,並且btnAsync01_Click將恢復(在UI線程上)。