2012-06-14 86 views
0

我有一個WPF應用程序,我必須做一個長時間運行的任務(基本上從網絡讀取)。只是給你一個快照我做的按鈕下面的事情請單擊使用任務的異步操作,但用戶界面仍然沒有反應

Dim t As Task(Of String) = Task.Factory.StartNew(Of String)(Function() 
                     'Thread.sleep is simulating long running task that will make UI unresponsive 
                     Thread.Sleep(10000) 
                     Return "Hello world from async task" 
                    End Function) 

     TextBlock1.Text = t.Result 

我不能使用基於事件的異步方法,因爲閱讀API中,我在我的計劃是指一個DLL確實存在,包含一個函數Public function ReadFromNetwork() as String 。此API正在對網絡進行異步調用以讀取長字符串並返回UI。所以,總之我在做TextBlock1.Text = ExternalDll.ReadFromNetwork()

但問題是,即使我使用任務異步,UI仍然沒有響應。

你能檢查我是否在代碼中丟失了某些東西。

任何幫助/建議將不勝感激 Thanx提前

回答

8

您在啓動任務後正在使用t.Result。這將使線程阻塞,直到任務完成 - 所有異步都是徒勞的。

您應該使用Task.ContinueWith附加延續,並將使用任務結果的代碼放入該延續中。這將允許用戶界面返回到處理任務執行期間的事件,然後在任務完成時觸發延續。傳入TaskScheduler.FromCurrentSynchronizationContext以確保繼續在右側線程上觸發。

請注意,在下一個版本的VB/C#中,所有這些將是,使用異步方法更容易得到。如果你能夠使用.NET 4.5候選版本,你應該考慮現在就嘗試一下 - 它會讓你的生活變得更簡單。

+0

是的,我知道...... .net 4.5帶來異步並等待關鍵字語言。但我的應用程序固有地被預Windows 8操作系統使用。 – Uday0119

+2

@ Uday0119:.NET 4.5並不侷限於Windows 8. –

+0

現在我得到一個異常,因爲「調用線程無法訪問此對象,因爲另一個線程擁有它。」從ContinueWith方法訪問TextBlock方法 – Uday0119

1

我想應該是這樣的

t.ContinueWith((result) => { TextBlock1.Text = result.Result}); 

還是你只是在發佈鬆動呢?您可能必須使用正確的調度程序,除此之外,這應該可以做到這一點

+0

現在我得到一個異常',因爲不同的線程擁有it.'從ContinueWith方法訪問TextBlock的 – Uday0119

+0

檢查超負荷工作調用線程不能訪問該對象繼續使用(Func <任務,TNewResult> continuationFunction,TaskScheduler調度程序);你可以傳遞UI調度器,你可以使用var uithread = TaskScheduler.FromCurrentSynchronizationContext(); – Dominik

2

你打電話給t.Result這將強制任務執行。 您應該使用ContinueWith異步獲取結果。

var action = delegate(Task<string> s) // to avoid cross thread exception 
     { 
      Action ac = delegate() { TextBlock1.Text = s.Result; }; 
      this.Dispatcher.Invoke(ac); 

     }; 

     t.ContinueWith(action); 

原諒我使用C#

相關問題