2012-04-08 149 views
6

我試圖在不凍結UI的情況下在後臺執行操作。在不凍結UI的情況下運行長時間任務

當然,我可以爲此使用BackgroundWorker。

但是,我只想用Task API來完成它。

我想:

async void OnTestLoaded(object sender, RoutedEventArgs e) 
{ 
    await LongOperation(); 
} 
// It freezes the UI 

async void OnTestLoaded(object sender, RoutedEventArgs e) 
{ 
    var task = Task.Run(()=> LongOperation()); 
    task.Wait(); 
} 


// It freezes the UI 

所以,我應該回去的BackgroundWorker?或者只有使用任務的解決方案?

+0

爲什麼很多人不喜歡BackgroundWorker?我喜歡它,並直接找到語法。 – Paparazzi 2012-04-08 20:15:04

+0

'BackgroundWorker'遠遠好於'Thread',但'基於Task'的API最終將佔據主導地位。我有[相關的博客文章](http://nitoprograms.blogspot.com/2010/08/various-implementations-of-asynchronous.html)。 'Task.Run'具有以下優點:(1)允許嵌套; (2)取消支持使用統一的'CancellationToken'系統; (3)異常使用正確的調用堆棧更自然地傳播; (4)更自然地檢索結果; (5)使用較少的資源(線程池而不是專用線程)。 – 2012-04-09 12:35:29

回答

12

你非常接近。

async void OnTestLoaded(object sender, RoutedEventArgs e) 
{ 
    await Task.Run(() => LongOperation()); 
} 

asyncdoes not execute a method on a thread pool thread

Task.Run對線程池線程執行操作,並返回表示該操作的Task

如果您在async方法中使用Task.Wait,那麼您的是doing it wrong。你應該在async方法await任務,永遠不會阻止他們。

+0

如果您在此特定示例中沒有使用異步或等待,會有什麼區別嗎? – Lukazoid 2014-11-21 13:03:47

+0

@Lukazoid:如果你的意思只是'Task.Run'而沒有'等待'它,那麼這會默默吞下'LongOperation'中的所有異常。 – 2014-11-21 13:06:44

+0

但是不會因爲'OnTestLoaded'是一個'async void'而吞噬異常嗎?嗯,從進一步閱讀看來,當使用異步無效時,異常將重新開始捕獲的'SynchronizationContext',沒有async/await,它會被吞噬,就像你說的那樣,是正確的嗎? – Lukazoid 2014-11-21 13:27:01

相關問題