简体   繁体   中英

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. 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.

The lists are presented to the user by binding the lists to the ItemsSource property of WPF's ListView controls. 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."

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. 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.

I've tried various different types of collections including ObservableCollection and ConcurrentBag , but they have the same problems.

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.

Am I missing something obvious? Thanks for any help!

Sometimes BindingOperations.EnableCollectionSynchronization can help.

Documentation

It enables a CollectionView object to participate in synchronized access to a collection that is used on multiple threads.

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.

Call EnableCollectionSynchronization(IEnumerable, Object) to inform WPF that you are using a simple lock mechanism. The call must occur on the UI thread.

The call must occur before using the collection on a different thread or before attaching the collection to the ItemsControl, whichever is later.

Generally, I call BindingOperations.EnableCollectionSynchronization(collection, lockObject) in the contructor of my view model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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