WPF 调度程序、后台工作人员和很多痛苦
好吧,这可能真的很简单,但我尝试的一切似乎都碰壁了。
我有一个具有两个属性的视图模型,它们绑定到我的 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);
})
);
但它仍然引发相同的跨线程错误。
我不太擅长线程,所以我不知道我可能做错了什么,有人可以帮我解决这个问题吗?
Ok this may be really simple but everything I try just seems to hit a brick wall.
I have a view model with two properties, which are bound to my WPF form:
bool IsWorking {get;set;}
ObservableCollection<OtherViewModel> PendingItems {get;set;}
I have a method that I call to fetch some new pending items from outlook, however I also what to show some sort of progress on the form(spinning progress bar), the progress bar visibility is bound to the IsWorking property on the ViewModel, and a grid is bound to PendingItems collection.
I would like to be able to set the IsWorking to true so the UI can show the progress bar, run the work in the background and then set the IsWorking to false after it's finished so the progress bar goes away.
I created a backgroudworker something like this:
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
Now worker_DoWork calls the method that goes of a fetches the pending items and adds them to PendingItems collection, everything runs in the background the UI is still responsive but I get the normal cross threaded error when trying to add to the collection. I wrapped the code that changes the collection in a dispatcher call:
// Update to show the status dialog.
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Render,
new Action(delegate()
{
this.PendingItems.Add(\\Blah);
})
);
but it still throws the same cross thread error.
I'm not very good with threading so I have no idea what I might be doing wrong, would someone be able to give me a hand with this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看看这里了解其他人如何创建线程安全的可观察值集合(所以你不必)。
have a look here for info on how other people have created thread safe observable collections (so you dont have to).
由于更新集合的代码是从后台线程调用的,因此 Dispatcher.CurrentDispatcher 是错误的调度程序。您需要保留对 UI 调度程序的引用,并在安排更新时使用该调度程序。
Since the code to update the collection is being called from a background thread, Dispatcher.CurrentDispatcher is the wrong dispatcher. You need to keep a reference to the UI's dispatcher and use that dispatcher when scheduling the update.
根据 http://msdn.microsoft.com/en -us/library/system.windows.threading.dispatcher.currentdispatcher
因为您在新线程(由工作线程创建)中调用 Dispatcher.CurrentDispatcher,所以它会创建新的调度程序对象。
因此,您应该以某种方式从调用线程(ui 线程)获取调度程序。
另一种选择是将 ui 调度程序作为参数传递给worker.RunWorkerAsync(object argument)
According to http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher
Because you call Dispatcher.CurrentDispatcher in the new thread (created by worker) it creates new dispatcher object.
So you should get dispatcher from the calling thread (ui thread) in some way.
Another option is to pass ui dispatcher to worker.RunWorkerAsync(object argument) as argument