Access ViewModel properties from a separate thread

In my wpf application, the multitask operation in my viewmodel is called using a separate thread. However, this function allows you to access several properties in the viewport that are bound to objects in the view. I tried to access them directly, and I see no complaints about them belonging to the user interface thread. I am interested to know the consequences of using them directly between threads.

+6
source share
3 answers

You can use ViewModel from any stream, including reading and writing. The only exception is data collection — data bindings must be written to the user interface stream, since the binding does not automatically marshal in the user interface stream (for example, simple bindings).

However, you should still have the correct sync for any record. Problems with synchronizing normal threads will occur, since ViewModel is another class.

As the saying goes, usually you will have to handle synchronization in a slightly different way than in many cases. Locks usually do not work in ViewModel, since WPF data binding will not block objects. Therefore, you should usually use Dispatcher.Invoke / BeginInvoke to redirect calls back to the user interface stream if necessary when synchronization is required in the ViewModel.

+5
source

There are no consequences from your usual thread safety problems. The only thing that is usually problematic for VM properties is ObservableCollections , which have a thread affinity.

+1
source

If you use the ObservableCollection extension with this, you can update it from a separate thread:

 /// <summary> /// Source: New Things I Learned /// Title: Have worker thread update ObservableCollection that is bound to a ListCollectionView /// http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx /// Note: Improved for clarity and the following of proper coding standards. /// </summary> /// <param name="e"></param> protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { // Use BlockReentrancy using (BlockReentrancy()) { var eventHandler = CollectionChanged; // Only proceed if handler exists. if (eventHandler != null) { Delegate[] delegates = eventHandler.GetInvocationList(); // Walk thru invocation list foreach (NotifyCollectionChangedEventHandler handler in delegates) { var currentDispatcher = handler.Target as DispatcherObject; // If the subscriber is a DispatcherObject and different thread if ((currentDispatcher != null) && (currentDispatcher.CheckAccess() == false)) { // Invoke handler in the target dispatcher thread currentDispatcher.Dispatcher.Invoke( DispatcherPriority.DataBind, handler, this, e); } else { handler(this, e); } } } } } /// <summary> /// Overridden NotifyCollectionChangedEventHandler event. /// </summary> public override event NotifyCollectionChangedEventHandler CollectionChanged; 
0
source

Source: https://habr.com/ru/post/903868/


All Articles