2013-07-08 31 views
0

在WPF應用程序中,我有一個按鈕綁定到我的視圖模型中的Command。該命令啓動任務以從數據庫獲取信息,然後更新一些屬性。如何在TaskScheduler.FromCurrentSychronizationContext中繼續使用Task.Result?

//list in vm to be bound to.. 
List<DataModel.Item> BoundList; 
//new command() => 
{ 
    var t = Task.Factory.StartNew<IEnumerable<DataModel.Item>>(() => 
     return datasvc.GetItems(); 
    ); 
    t.ContinueWith(t2 => { 
     BoundList = t.Result; 
    }, TaskScheduler.FromCurrentSychronizationContext); 
} 

該項目上t.Result報告生成錯誤,當我使用FromCurrentSynchronizationContext標誌,但是當它不存在沒有生成錯誤。問題是我得到一個沒有響應的用戶界面。

我在做什麼不正確?

+0

你什麼錯誤? – SLaks

+0

調用'Task.Run()'。或者讓它實際上是異步的,以便完全避免後臺線程。 – SLaks

+0

我不能在這個項目中使用.NET 4.5,所以Asych/Await的東西不適用於我。 –

回答

3

這不是一個標誌,它是一種靜態方法。此外,T2是任務的結果,所以你不需要原始任務存儲爲一個單獨的變量:

Task.Factory.StartNew(datasvc.GetItems) 
    .ContinueWith( 
     t => 
     { 
      BoundList = t.Result; 
     }, TaskScheduler.FromCurrentSychronizationContext()); 

如果你Task對象是在UI線程中運行(因此它凍結),這可能是因爲您已經在線程池中運行了多個線程。默認情況下,Task將在ThreadPool線程上運行,除非它們全部被使用。

但是,您可以通知.NET它是一個長時間運行的操作,並且它通常會生成其他線程來阻止您的UI凍結。

MSDN

TaskCreationOptions.LongRunning
指定一個任務將是涉及比細粒度的系統更少,更大的 組件 長期運行,粗粒度操作。它向 TaskScheduler提供了可能需要超額認購的提示。超額預訂 可讓您創建比可用數量的硬件線程更多的線程。

所以,你會改變你的任務創建到:

Task.Factory.StartNew(datasvc.GetItems, TaskCreationOptions.LongRunning) 
+0

這樣做。現在它編譯,但我仍然得到一個凍結的UI :(回到繪圖板 –

+0

@MikeCaron't.Result'返回多少項?如果它返回了大量的項目,並且BoundList綁定到UI ,這可能會使界面凍結 – PoweredByOrange

+1

@MikeCaron我加入到我的答案,希望能解決這個問題 –