Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Dispatcher, Background worker and a whole lot of pain

Ok this may be really simple but everything I try just seems to hit a brick wall.

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

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

I have a method that I call to fetch some new pending items from outlook, however I also what to show some sort of progress on the form(spinning progress bar), the progress bar visibility is bound to the IsWorking property on the ViewModel, and a grid is bound to PendingItems collection.

I would like to be able to set the IsWorking to true so the UI can show the progress bar, run the work in the background and then set the IsWorking to false after it's finished so the progress bar goes away.

I created a backgroudworker something like this:

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

Now worker_DoWork calls the method that goes of a fetches the pending items and adds them to PendingItems collection, everything runs in the background the UI is still responsive but I get the normal cross threaded error when trying to add to the collection. I wrapped the code that changes the collection in a dispatcher call:

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

but it still throws the same cross thread error.

I'm not very good with threading so I have no idea what I might be doing wrong, would someone be able to give me a hand with this?

like image 730
Nathan W Avatar asked Feb 10 '10 23:02

Nathan W


2 Answers

Since the code to update the collection is being called from a background thread, Dispatcher.CurrentDispatcher is the wrong dispatcher. You need to keep a reference to the UI's dispatcher and use that dispatcher when scheduling the update.

like image 37
Carlos Avatar answered Sep 21 '22 23:09

Carlos


have a look here for info on how other people have created thread safe observable collections (so you dont have to).

like image 175
Aran Mulholland Avatar answered Sep 17 '22 23:09

Aran Mulholland