There is a WPF application in C #. One of the operations is the update of the ObservableCollection content in the view model class is quite long and at the same time constant (updated every few seconds). In order not to start, the UI decided to output to a separate thread using async - await - Task . Code :

  private async void ResetAsync() { await Update(); } private Task Update() { return Task.Run(async ()=> { while (true) { // Do some... await Task.Delay(2000); } }); } 

However, there is a problem related to the fact (correct if not right) that the collection of the view model should be updated within the UI stream and not the one that I selected through Async - Await

This CollectionView type does not support changes to its SourceCollection from a stream other than the Dispatcher stream.

Now I need to use Dispatcher to return the result to the UI stream? Tell me how to do this?

  • Comments are not intended for extended discussion; conversation moved to chat . - PashaPash

1 answer 1

Make a service, for example:

 public interface IContext { void Invoke(Action action); void BeginInvoke(Action action); } 

And its implementation:

 public sealed class WpfDispatcherContext : IContext { private readonly Dispatcher _dispatcher; public WpfDispatcherContext() : this(Dispatcher.CurrentDispatcher) { } public WpfDispatcherContext(Dispatcher dispatcher) { this._dispatcher = dispatcher; } public void Invoke(Action action) { this._dispatcher.Invoke(action); } public void BeginInvoke(Action action) { this._dispatcher.BeginInvoke(action); } } 

Next, register it in your DI container and pull up on the twist model:

 public class ViewModel { private readonly IContext _context; private ObservableCollection<string> _values; public IEnumerable<string> Values => _values; public ViewModel(IContext context) { _context = context; } private async void ResetAsync() { await Update(); } private Task Update() { return Task.Run(async ()=> { while (true) { // Do some... _context.Invoke(() => _values.Add("New String Value")); // Do some more... await Task.Delay(2000); } }); } } 

If you do not use DI containers, then just use the handles in the designer to view the model and create an instance of the service. This can then be easily fixed when you start using DI containers:

 public ViewModel() { _context = new WpfDispatcherContext(); } 
  • What is a DI container? - Sergey
  • @ Sergey and how are you getting services? Or do you hardcod their creation in each twist model? - MihailPw
  • another question - what is meant by the service? - Sergey
  • @ Sergey I call IContext interface and its implementation WpfDispatcherContext service (in fact it performs the role of a service) - MihailPw
  • five
    Well zache-ee ?! Why make your bike when there is a standard class SynchronizationContext? - Pavel Mayorov