Instantiating an object in a background worker causes the UI to freeze up

我的梦境 提交于 2019-12-24 14:35:59

问题


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...


回答1:


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




回答2:


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.



来源:https://stackoverflow.com/questions/7553884/instantiating-an-object-in-a-background-worker-causes-the-ui-to-freeze-up

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!