好的,这可能非常简单,但我尝试的所有东西似乎都碰壁了。
我有一个包含两个属性的视图模型,这些属性绑定到我的WPF表单:
bool IsWorking {get;set;}
ObservableCollection<OtherViewModel> PendingItems {get;set;}
我有一个方法,我调用从outlook中获取一些新的待处理项,但是我还要在表单上显示某些进度(旋转进度条),进度条可见性绑定到IsWorking属性上ViewModel和一个网格绑定到PendingItems集合。
我希望能够将IsWorking设置为true,以便UI可以显示进度条,在后台运行工作,然后在完成后将IsWorking设置为false,这样进度条就会消失。
我创建了一个这样的背景工作者:
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);
})
);
但它仍会抛出相同的交叉线程错误。
我对线程不是很好,所以我不知道我可能做错了什么,有人能帮我一把吗?
答案 0 :(得分:5)
查看here,了解其他人如何创建线程安全的可观察集合(所以你不必这样做)。
答案 1 :(得分:4)
由于正在从后台线程调用更新集合的代码,因此Dispatcher.CurrentDispatcher是错误的调度程序。您需要保留对UI调度程序的引用,并在计划更新时使用该调度程序。
答案 2 :(得分: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);
})
);
}