简体   繁体   English

如何处理 WPF 数据库应用程序中的调度程序问题?

[英]How do I deal with dispatcher issue in WPF database application?

I'm developing an application (using C# and WPF) that provides a user interface to an SQL database.我正在开发一个应用程序(使用 C# 和 WPF),它为 SQL 数据库提供用户界面。 Multiple instances of the application access and modify the database simultaneously so on a regular basis, the application requests records from the database that have been modified since the last request and those records are loaded into lists of complex classes using XML deserialization.应用程序的多个实例同时访问和修改数据库,因此应用程序会定期从数据库中请求自上次请求以来已修改的记录,并将这些记录加载到使用 XML 反序列化的复杂类列表中。

The lists are presented to the user by binding the lists to the ItemsSource property of WPF's ListView controls.通过将列表绑定到 WPF 的 ListView 控件的 ItemsSource 属性,将列表呈现给用户。 This works great initially, but when the list is updated (specifically when items are added or removed), I get an this error:这最初效果很好,但是当列表更新时(特别是在添加或删除项目时),我收到此错误:

"This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread." “这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection。”

I understand the problem, the UI thread wants to control the bound dataset and add or remove data through the safety of the ListView's dispatcher.我理解这个问题,UI 线程想要通过 ListView 的调度程序的安全性来控制绑定的数据集并添加或删除数据。 However, it seems that there must be a way to have a thread safe UI to data that is not exclusive to the single user.但是,似乎必须有一种方法可以为非单个用户专有的数据提供线程安全的 UI。

I've tried various different types of collections including ObservableCollection and ConcurrentBag , but they have the same problems.我尝试了各种不同类型的 collections 包括ObservableCollectionConcurrentBag ,但它们有同样的问题。

I can circumvent the issue by binding to a copy of the list ( List.ToList<>() ), and use an event to trigger re-binding to a new copy whenever the list is updated, but that seem clumsy, defeats the purpose of ListViews and binding, and is far from the elegance of C# or WPF.我可以通过绑定到列表的副本( List.ToList<>() )来规避这个问题,并在列表更新时使用事件触发重新绑定到新副本,但这看起来很笨拙,违背了目的ListViews 和绑定,远非 C# 或 WPF 的优雅。

Am I missing something obvious?我错过了一些明显的东西吗? Thanks for any help!谢谢你的帮助!

Sometimes BindingOperations.EnableCollectionSynchronization can help.有时BindingOperations.EnableCollectionSynchronization会有所帮助。

Documentation 文档

It enables a CollectionView object to participate in synchronized access to a collection that is used on multiple threads.它使 CollectionView object 能够参与对在多个线程上使用的集合的同步访问。

BindingOperations.EnableCollectionSynchronization(collection, lockObject);

To use a collection on multiple threads, one of which is the UI thread that owns the ItemsControl, you must instantiate an object to lock when accessing the collection.要在多个线程上使用集合,其中之一是拥有 ItemsControl 的 UI 线程,您必须实例化 object 以在访问集合时锁定。

Call EnableCollectionSynchronization(IEnumerable, Object) to inform WPF that you are using a simple lock mechanism.调用 EnableCollectionSynchronization(IEnumerable, Object) 通知 WPF 您正在使用简单的锁定机制。 The call must occur on the UI thread.调用必须发生在 UI 线程上。

The call must occur before using the collection on a different thread or before attaching the collection to the ItemsControl, whichever is later.调用必须在在不同线程上使用集合之前或在将集合附加到 ItemsControl 之前发生,以较晚者为准。

Generally, I call BindingOperations.EnableCollectionSynchronization(collection, lockObject) in the contructor of my view model.通常,我在视图 model 的构造函数中调用BindingOperations.EnableCollectionSynchronization(collection, lockObject)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM