2010-02-10 62 views
6

的好,這可能是很簡單的,但一切我嘗試似乎只是撞到南牆。WPF調度,背景工人和很多痛苦

我有兩個屬性,這必將對我的WPF表單視圖模型:

bool IsWorking {get;set;} 
ObservableCollection<OtherViewModel> PendingItems {get;set;} 

我有打電話來從Outlook中的一些新的待批項目的方法,但是我也應該顯示哪些某種形式(紡紗進度條)的進展,進度條的知名度勢必對視圖模型的IsWorking屬性,柵格勢必PendingItems集合。

我希望能夠將IsWorking設置爲true,以便UI可以顯示進度條,在後臺運行該工作,然後在完成後將IsWorking設置爲false,以便進度條消失。

我創建了一個backgroudworker是這樣的:

 worker = new BackgroundWorker(); 
     worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
     worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 
     worker.RunWorkerAsync(); 

現在worker_DoWork調用雲的提取未決的項目,並將它們添加到PendingItems收集的方法,一切都在後臺運行的UI仍然響應,但嘗試添加到集合時,出現正常的交叉線程錯誤。我在調度程序調用中打包更改集合的代碼:

 // Update to show the status dialog. 
     Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Render, 
          new Action(delegate() 
          { 
           this.PendingItems.Add(\\Blah); 
          }) 
         ); 

但它仍會引發相同的交叉線程錯誤。

我不是很好的線程,因此我不知道我可能是做錯了,會有人能夠給我個忙?

回答

5

看看here瞭解其他人如何創建線程安全可觀察集合(所以你不必)。

+0

非常感謝你的偉大工程。 – 2010-02-11 00:45:21

+0

第二個鏈接已死亡。有任何想法嗎? – brumScouse 2012-08-15 11:22:36

+0

@brumScouse嘗試現在 – 2012-08-20 06:18:29

4

由於要從後臺線程調用更新集合的代碼,因此Dispatcher.CurrentDispatcher是錯誤的調度程序。您需要保留對UI調度程序的引用,並在調度更新時使用該調度程序。

0

根據http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher 由於您在新線程(由worker創建)中調用Dispatcher.CurrentDispatcher,它會創建新的調度程序對象。 所以你應該以某種方式從調用線程(ui線程)獲得調度程序。 另一種選擇是UI調度作爲參數傳遞給worker.RunWorkerAsync(對象參數)

worker = new BackgroundWorker(); 
worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 
worker.RunWorkerAsync(Dispatcher.CurrentDispatcher); 

... 

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Dispatcher dispatcher = e.Argument as Dispatcher; // this is right ui dispatcher 

    // Update to show the status dialog. 
    dispatcher.Invoke(DispatcherPriority.Render, 
          new Action(delegate() 
          { 
           this.PendingItems.Add(\\Blah); 
          }) 
         ); 

}