如何使用 MVVM 从 BackgroundWorker 内部更新 ObservableCollection?
这两天我正在尝试解决以下问题: 我有一个 WPF 控件,其中 WrapPanel 绑定到 ObservableCollection。操作会更改 ObservableCollection 的内容。内容加载到BackgroundWorker 中。在导致内容更改的操作之后,foreach 循环中需要新内容。问题是内容加载很慢,所以需要一点准备。
我的第一次尝试是等待后台工作程序,直到 IsBusy 属性设置为 false。但 IsBusy 属性在等待期间从未改变! 第二次尝试是尝试直接从BackgroundWorker 操作ObservableCollection。当然没有成功,因为 ObservableCollection 位于与 BackgroundWorker 不同的另一个线程中。
我读了很多关于如何跨线程操作内容的内容。但它们都不起作用。尝试使用 Dispatcher“ThreadSafeObservableCollection”解决方案,.....
有人可以告诉我如何解决这个问题吗? 有没有一种简单的方法可以在另一个线程中编辑 UI 线程的内容? 或者我如何正确等待BackgroundWorker完成?
编辑: 但我怎样才能等待BackgroundWorker完成呢???
since two days I am trying to solve the following problem:
I have a WPF control where a WrapPanel is bound to an ObservableCollection. An action changes the content of the ObservableCollection. The content is loaded in a BackgroundWorker. Immediately after the action that caused the content change, the new content is needed in a foreach-loop. The problem is that the loading of the content is slow, so it needs a bit to get ready.
My first attempt was to wait for the backgroundworker until the IsBusy property is set to false. But the IsBusy property never changed while waiting!
Second attempt was to try to manipulate the ObservableCollection directly from the BackgroundWorker. Of course no success because the ObservableCollection is in another thread than the BackgroundWorker.
I read really really much about how to manipulate content in cross-thread-wide. But none of them worked. Tried solutions with Dispatcher, "ThreadSafeObservableCollection", .....
Might anyone tell me how I can solve that problem?
Is there a simple way to edit content of the UI thread within another thread?
Or how do I wait correctly for the BackgroundWorker to get finished?
EDIT:
But how can I wait for the BackgroundWorker to get finished???
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
BackgroundWorker 可以通过两种方式帮助您。
要在 BGWorker 运行时更新集合,请使用
ProgressChanged
事件。此事件的名称具有误导性 - 虽然您可以更新任务的进度,但实际上您可以通过传递对象来将其用于 UI(调用)线程中需要完成的任何操作ProgressChangedEventArgs 的 UserState 属性。BGWorker 完成时也会有一个事件。同样,您可以在
RunWorkerCompleted
事件中的 RunWorkerCompletedEventArgs 的 Result 属性中将任何您想要的信息传递回给它。以下代码来自另一个线程 我回答了有关BackgroundWorker的问题:
The BackgroundWorker can help you in two ways.
To update the collection while the BGWorker is running, use the
ProgressChanged
event. The name of this event is misleading - while you can update the progress of a task, you can use actually use it for anything that needs to be done in the UI (calling) thread by passing an object using the UserState property of the ProgressChangedEventArgs.The BGWorker also has an event when it finishes. Again, you can pass any information back to it that you'd like in the Result property of the RunWorkerCompletedEventArgs in the
RunWorkerCompleted
event.The following code is from another thread that I answered about BackgroundWorker:
将
ObservableCollection.Add
推送到 UI 线程的调度程序应该可以工作。Pushing the
ObservableCollection.Add
to the dispatcher of the UI thread should work.您可以在BackgroundWorker.RunWorkerCompleted 事件处理程序中更新集合。它在您启动它的同一同步上下文中运行,通常是一个 UI 线程,因此您可以从那里安全地使用任何与 UI 相关的内容。
You can update your collection in the BackgroundWorker.RunWorkerCompleted event handler. It runs in the same synchronization context you started it which is a UI thread usually so you can safely use any UI related stuff from there.
BackGroundWorker 完成后会触发一个事件。
我在类似情况下一直在做的是:
我有一个不是可观察集合的列表,
因此与集合的所有交互都在同一线程上 - 复制通常不是昂贵的部分。
The BackGroundWorker fires an event when it is finished.
What I have been doing in a similar situation is :
I have a list that is not an observablecollecion
so all interaction with the collection is on same thread - the copying is usually not the expensive part.