问题
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