使用 MVVM 中的后台工作者更新 ObservableCollection
好的,我最近实现了一个后台工作者来执行数据的保存和加载。
然而,事实证明,让它在保存命令上运行是很困难的。
基本上,我的保存命令生成一个事件,通知集合视图模型已添加项目并且该项目应添加到其自己的 ObservableCollection 中。
此时,我得到通常的异常,说我无法在不同线程上更新 ICollection。我尝试创建一个调用 Dispatcher.Invoke 的新列表类型,但这仍然会生成相同的异常。
我想知道其他人是否对如何最好地解决这个问题有任何建议?
所以目前我有一个继承自 ObservableCollection 的类:
public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
{
public ThreadSafeObservableCollection(List<T> collection)
: base(collection)
{
dispatcher = Dispatcher.CurrentDispatcher;
rwLock = new ReaderWriterLock();
}
protected override void InsertItem(int index, T item)
{
if (dispatcher.CheckAccess())
{
if (index > this.Count)
return;
LockCookie c = rwLock.UpgradeToWriterLock(-1);
base.InsertItem(index, item);
rwLock.DowngradeFromWriterLock(ref c);
}
else
{
object[] obj = new object[] { index, item };
dispatcher.Invoke(
DispatcherPriority.Send,
(SendOrPostCallback)delegate { InsertItemImpl(obj); },
obj);
}
}
然后我有一个视图模型类,它有一个执行保存的后台工作人员。
保存完成后,将向另一个视图模型触发一个事件以更新其列表。
protected override void OnObjectAddedToRepository(object sender, ObjectEventArgs<cdAdministrators> e)
{
Dispatcher x = Dispatcher.CurrentDispatcher;
var viewModel = new AdministratorViewModel(e.EventObject, DataAccess);
viewModel.RecentlyAdded = true;
viewModel.ItemSelected += this.OnItemSelected;
this.AllViewModels.Add(viewModel);
RecentlyAddedViewModel = viewModel;
OnPropertyChanged(null);
}
这两个列表都是由单独的后台工作线程创建的。
Ok, I recently implemented a background worker to perform saving and loading of data.
However, getting this to work on a save command has proved difficult.
Basically, my save command generates an event, that notifies a collection view model, that an Item has been added and that the item should be added to its own ObservableCollection.
At this point, I get the usual exception saying I can NOT update an ICollection on a different thread. I have tried creating a new list type that calls Dispatcher.Invoke
, however this still generates the same exception.
I was wondering whether anyone else has any suggestions on how best to tackle this?
So currently I have a class that Inherits from ObservableCollection:
public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
{
public ThreadSafeObservableCollection(List<T> collection)
: base(collection)
{
dispatcher = Dispatcher.CurrentDispatcher;
rwLock = new ReaderWriterLock();
}
protected override void InsertItem(int index, T item)
{
if (dispatcher.CheckAccess())
{
if (index > this.Count)
return;
LockCookie c = rwLock.UpgradeToWriterLock(-1);
base.InsertItem(index, item);
rwLock.DowngradeFromWriterLock(ref c);
}
else
{
object[] obj = new object[] { index, item };
dispatcher.Invoke(
DispatcherPriority.Send,
(SendOrPostCallback)delegate { InsertItemImpl(obj); },
obj);
}
}
I then have a view model class that has a background worker which carries out the save.
Once the save is complete, an event is fired to another view model to update its list.
protected override void OnObjectAddedToRepository(object sender, ObjectEventArgs<cdAdministrators> e)
{
Dispatcher x = Dispatcher.CurrentDispatcher;
var viewModel = new AdministratorViewModel(e.EventObject, DataAccess);
viewModel.RecentlyAdded = true;
viewModel.ItemSelected += this.OnItemSelected;
this.AllViewModels.Add(viewModel);
RecentlyAddedViewModel = viewModel;
OnPropertyChanged(null);
}
Both lists are created by a separate background worker thread.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您有将项目添加到可观察集合(可能在视图模型中)的代码,请将
Add
调用包装在Dispatcher.BeginInvoke
调用中。不可否认,这意味着视图模型需要了解调度程序,这使得测试变得很困难...幸运的是,引入您自己的 IDispatcher 接口并以正常方式使用依赖项注入并不太难。
Where you've got code which adds the item to the observable collection (presumably in the view model), wrap that
Add
call in aDispatcher.BeginInvoke
call.Admittedly that means the view model needs to know about the dispatcher, which then becomes awkward to test... fortunately it's not too hard to introduce your own
IDispatcher
interface and use dependency injection in the normal way.这个怎么样?
How about this?
我发现了一篇博客文章,它使用调度程序管理 ObeservableCollection 的所有方法。这是代码片段,请参阅帖子< /a> 对于整个班级。
I found a blog post that uses the Dispatcher to manage all of the ObeservableCollection's methods. Here is a snip-it of the code, see the post for the entire class.