6

好吧,这可能真的很简单,但我尝试的一切似乎都碰壁了。

我有一个具有两个属性的视图模型,它们绑定到我的 WPF 表单:

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

我有一个方法,我调用它来从 Outlook 中获取一些新的待处理项目,但是我还要在表单上显示某种进度(旋转进度条),进度条可见性绑定到 ViewModel 上的 IsWorking 属性,并且网格绑定到 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);
                            })
                          );

但它仍然会引发相同的跨线程错误。

我对线程不是很好,所以我不知道我可能做错了什么,有人能帮我解决这个问题吗?

4

3 回答 3

5

这里查看有关其他人如何创建线程安全可观察集合的信息(因此您不必这样做)。

于 2010-02-11T00:07:19.103 回答
4

由于从后台线程调用更新集合的代码,因此 Dispatcher.CurrentDispatcher 是错误的调度程序。您需要保留对 UI 调度程序的引用,并在安排更新时使用该调度程序。

于 2010-02-11T20:00:49.963 回答
0

根据http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher 因为您在新线程(由工作人员创建)中调用 Dispatcher.CurrentDispatcher 它会创建新的调度程序对象。所以你应该以某种方式从调用线程(ui线程)获取调度程序。另一种选择是将 ui 调度程序作为参数传递给 worker.RunWorkerAsync(object argument)

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);
                            })
                          );

}
于 2012-07-26T11:41:27.347 回答