c# – BackgroundWorker返回错误的线程

在我的应用程序中,我使用以下代码创建了一个新的UI-Thread:

Thread thread = new Thread(() =>
    {
        MyWindow windowInAnotherThread = new MyWindow();
        windowInAnotherThread.Show();
        System.Windows.Threading.dispatcher.Run();
    }) { IsBackground = true };
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();

这给了我一个问题:

在MyWindow类的构造函数中,执行BackgroundWorker.在RunWorkerCompleted中,应该使用BackgroundWorker正在计算的某些数据更新Control.

我已经构建了一个小样本,它说明了这一点:

public partial class MyWindow : Window {
    public MyWindow() {
        InitializeComponent();

        var bw = new BackgroundWorker();
        bw.DoWork += bw_DoWork;
        bw.RunWorkerCompleted += bw_RunWorkerCompleted;
        bw.RunWorkerAsync();
    }

    void bw_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e) {
        this.Title = "Calculated title";
    }

    void bw_DoWork(object sender,DoWorkEventArgs e) {
        Thread.Sleep(3000);
    }
}

在bw_RunWorkerCompleted()中,我得到一个InvalidOperationException(调用线程无法访问此对象,因为另一个线程拥有它.).看起来,BackgroundWorker没有返回到从中启动它的正确的UI-Thread.

有人可以帮助我,我能做些什么来解决这个问题?我无法更改正在执行BackgroundWorker的代码,因为它位于我使用的框架中.但我可以在RunWorkerCompleted-Event中做其他事情.但我不知道,如何解决这个问题.

解决方法

问题是窗口过早创建.该线程还没有同步上下文.您可以通过在BGW构造函数调用上设置断点来查看这是调试器,并查看Thread.CurrentThread.ExecutionContext.SynchronizationContext.它是空的.这是BGW用来决定如何编组RunWorkerCompleted事件的方法.其中没有同步上下文,事件在线程池线程上运行并调用愤怒.

您需要尽快初始化调度程序.不是100%这是正确的方法,但似乎确实有效:

Thread thread = new Thread(() => {
            System.Windows.Threading.dispatcher.Currentdispatcher.BeginInvoke(new Action(() => {
                MyWindow windowInAnotherThread = new MyWindow();
                windowInAnotherThread.Show();
            }));
            System.Windows.Threading.dispatcher.Run();
        }) { IsBackground = true };
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();

您还必须明确强制线程关闭.将此方法添加到MyWindow:

protected override void OnClosed(EventArgs e) {
        dispatcher.BeginInvokeShutdown(System.Windows.Threading.dispatcherPriority.Background);
    }

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...