2010-02-10 60 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); 
          }) 
         ); 

}