在后台工作线程中实例化一个对象会导致UI冻结
本文关键字:UI 冻结 一个对象 实例化 后台 工作 线程 | 更新日期: 2023-09-27 18:09:55
这就是我现在所拥有的,但是当我调用Dispatcher.BeginInvoke()
时,我的UI冻结了:
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();
dispatcher.BeginInvoke
中的第一行导致我的UI
冻结。ReportPreviewView reportPreviewView = new ReportPreviewView(reportViewModel);
注意: ReportPreviewView
为报告请求创建相关视图。可以是Devexpress
、C1
或pivot reports
。
一旦我删除dispatcher.BeginInvoke
,我得到这个错误:
The calling thread must be STA, because many UI components require this.
所以我的问题是,我需要做些什么来绕过这个?
使用BackgroundWorker
的全部原因是为了让我的UI
始终保持响应。
我是新的multithreading
,所以也许我得到的结构都错了…
调度器。BeginInvoke会异步地启动你封装在Action中的代码,但是Do_Work处理程序也会被BackgroundWorker异步更新,所以你不应该使用它。
主要问题是你试图从另一个线程访问UI实例,而windows不允许这样做:只有主线程可以访问UI元素实例。
正确的方法是使用Control。如果您使用的是windows窗体,请调用
关于winforms线程模型的深度文章
这个故事的寓意是,所有的UI元素都需要在UI线程上创建!
也就是说,如果UI元素的创建花费了很长时间,UI将会冻结。把所有繁重的工作放在Task
或BackgroundWorker
中。