WPF manager, help desk and a lot of pain

Well, it can be very simple, but everything I try to do seems to hit a brick wall.

I have a view model with two properties that are bound to my WPF form:

bool IsWorking {get;set;} ObservableCollection<OtherViewModel> PendingItems {get;set;} 

I have a method that I call to get some new pending items from Outlook, however I also want to show some progress in the form (a rotating progress bar), the visibility of the progress bar is tied to the IsWorking property on the ViewModel and the grid is tied to the PendingItems collection.

I would like to set IsWorking to true so that the user interface can display a progress bar, start work in the background, and then set IsWorking to false after it is completed so that the progress bar disappears.

I created a backgroudworker something like this:

  worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandler(worker_DoWork); worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); worker.RunWorkerAsync(); 

Worker_DoWork now calls a method that retrieves pending items and adds them to the PendingItems collection, everything works in the background, the user interface is still responsive, but when I try to add to the collection, I get the usual pass-through error. I wrapped the code that changes the collection in the dispatcher call:

  // Update to show the status dialog. Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Render, new Action(delegate() { this.PendingItems.Add(\\Blah); }) ); 

but he still throws the same cross-flow error.

I am not very fluent in threads, so I have no idea what I can do wrong, could someone give me a hand with this?

+6
multithreading backgroundworker wpf mvvm dispatcher
source share
3 answers

look here for information on how other people created thread-safe observable collections (so you don't need to).

+5
source share

Since the code to update the collection is called from the background thread, Dispatcher.CurrentDispatcher is the wrong dispatcher. You need to save the link to the user interface manager and use the manager when planning the upgrade.

+4
source share

According to http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher Since you call Dispatcher.CurrentDispatcher in a new thread (created by worker), it creates a new dispatcher object. Therefore, you must somehow get the dispatcher from the calling thread (ui thread). Another option is to pass the ui to the manager for worker.RunWorkerAsync (object argument) as an argument

 worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandler(worker_DoWork); worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); worker.RunWorkerAsync(Dispatcher.CurrentDispatcher); ... private void worker_DoWork(object sender, DoWorkEventArgs e) { Dispatcher dispatcher = e.Argument as Dispatcher; // this is right ui dispatcher // Update to show the status dialog. dispatcher.Invoke(DispatcherPriority.Render, new Action(delegate() { this.PendingItems.Add(\\Blah); }) ); } 
0
source share

All Articles