1

This is what i have at the moment, but when i call Dispatcher.BeginInvoke(), my UI freezes up:

        BackgroundWorker backgroundWorker = new BackgroundWorker();
        backgroundWorker.WorkerSupportsCancellation = true;
        backgroundWorker.WorkerReportsProgress = true;


        ViewModel.GenerateReport(backgroundWorker, Dispatcher);

ViewModel:

backgroundWorker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            try
            {
                ReportViewModel reportViewModel = new ReportViewModel(SessionContext, Mediator, reportDashboardViewModel.ReportRequest, false);

                dispatcher.BeginInvoke((Action)(() =>
                {
                    ReportPreviewView reportPreviewView = new ReportPreviewView(reportViewModel);
                    reportPreviewView.ReportName = reportDashboardViewModel.ReportRequest.Report.ReportName;

                    ReportView = reportPreviewView;
                }));
            }
            catch (Exception exception)
            {
                backgroundWorker.ReportProgress(0, "There Was an Error generating the report");
                backgroundWorker.CancelAsync();
                throw;
            }
        };

        backgroundWorker.RunWorkerAsync();

The first line in dispatcher.BeginInvoke causes my UI to freeze up. ReportPreviewView reportPreviewView = new ReportPreviewView(reportViewModel);

Note: ReportPreviewView creates the relevant view for the report request. May it be Devexpress, C1 or pivot reports.

As soon as i remove the dispatcher.BeginInvoke, i get this error:

The calling thread must be STA, because many UI components require this.

So my question is, what do i need to do to get around this?

The whole reason for using a BackgroundWorker was so that my UI stays responsive at all times.

I am new to multithreading,so maybe i got the structure all wrong...

Willem
  • 9,166
  • 17
  • 68
  • 92
  • 2
    possible duplicate of [How can I make a background worker thread set to Single Thread Apartment?](http://stackoverflow.com/questions/4685237/how-can-i-make-a-background-worker-thread-set-to-single-thread-apartment) – Hans Passant Sep 26 '11 at 12:08
  • Using BeginInvoke inside DoWork negates the Bgw. `new ReportPreviewView()` is executed on the main thread. So yes, that can hang your Gui. – H H Sep 26 '11 at 13:06
  • @Henk Holterman: Thanks for the response. What do u suggest i should do? – Willem Sep 26 '11 at 13:25
  • 1
    Take a look at Hans's link about STA threads. – H H Sep 26 '11 at 13:29
  • 1
    you should just do the long running and not ui related processes in the DoWork, eg. Load Data from DB. if the datagrid or whatever cause the ui to be not responsive you should look at virtualization for ItemsScontrols. – blindmeis Sep 26 '11 at 13:36

2 Answers2

2

Disptacher.BeginInvoke launches the code you encapsulated withing an Action ansynchronoulsy, but the Do_Work handler is also updated async by the BackgroundWorker, so you should't use it.

The main problem is that you are trying to access an UI instance from another thread, and windows disallow that: only the main thread can access an UI element instance.

The correct way to do it is using Control.Invoke if you are using windows Forms.

A deep article about the winforms threading model

Ricardo Amores
  • 4,597
  • 1
  • 31
  • 45
  • Thanks for the response Ricky. I am using wpf... Would i use the same approach? – Willem Sep 26 '11 at 11:04
  • @Willem - You need to use Control.Invoke within ReportProgress since that belongs to your application. – Security Hound Sep 26 '11 at 12:16
  • Sorry Ricky. I don't understand what you mean. How would i call `Control.Invoke` within ReportProgress? Is this the backgroundworkers `backgroundWorker.WorkerReportsProgress`? My main problem is just the creation of the `ReportPreviewView`. I need that to basically happen on its own thread... So what do you suggest i do? – Willem Sep 26 '11 at 12:22
  • Sorry Willem, I have no experience with WPF (learning in mi free time right now) so I can't help you didn't see the wpf tag :( – Ricardo Amores Sep 26 '11 at 16:45
0

Moral of the story, all UI elements needs to be created on the UI thread!

That being said, if the creation of the UI element takes a long time, the UI will freeze up. Take all the heavy lifting and put it in a Task or BackgroundWorker.

Then you will have a more responsive UI.

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
Willem
  • 9,166
  • 17
  • 68
  • 92