在后台工作线程中实例化一个对象会导致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为报告请求创建相关视图。可以是DevexpressC1pivot reports

一旦我删除dispatcher.BeginInvoke,我得到这个错误:

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

所以我的问题是,我需要做些什么来绕过这个?

使用BackgroundWorker的全部原因是为了让我的UI始终保持响应。

我是新的multithreading,所以也许我得到的结构都错了…

在后台工作线程中实例化一个对象会导致UI冻结

调度器。BeginInvoke会异步地启动你封装在Action中的代码,但是Do_Work处理程序也会被BackgroundWorker异步更新,所以你不应该使用它。

主要问题是你试图从另一个线程访问UI实例,而windows不允许这样做:只有主线程可以访问UI元素实例。

正确的方法是使用Control。如果您使用的是windows窗体,请调用

关于winforms线程模型的深度文章

这个故事的寓意是,所有的UI元素都需要在UI线程上创建!

也就是说,如果UI元素的创建花费了很长时间,UI将会冻结。把所有繁重的工作放在TaskBackgroundWorker中。