设置WinForms.Form所有者时的跨线程异常 - 如何正确执行?

时间:2011-03-11 13:45:43

标签: c# winforms invoke

我有一个主UI线程,它运行应用程序并创建主窗口表单(让我们称之为W)。我还有一个我旋转的辅助线程,它创建了一个对话框(让我们称之为B)。

我想将对话框B的所有者设置为主窗口WB所有者的设置发生在创建B的线程上。基本上是:

b.Owner = w;

但是这会引发一个跨线程异常,告诉我我正在尝试从错误的线程访问W对象。

所以我尝试在Control.Invoke W上使用B来执行主UI线程上的代码。但是,我得到了同样的错误,告诉我我正试图从错误的线程访问System.InvalidOperationException was unhandled by user code Message=Cross-thread operation not valid: Control 'B' accessed from a thread other than the thread it was created on. Source=System.Windows.Forms

{{1}}

我该怎么做?

3 个答案:

答案 0 :(得分:5)

这是Winforms中的一个错误,Windows实际上支持使所有者成为在另一个线程上创建的窗口。有一种方法可以禁用该检查,您应该永远做的事情。除非我不得不假设:

    private void button1_Click(object sender, EventArgs e) {
        var t = new Thread(() => {
            Control.CheckForIllegalCrossThreadCalls = false;
            var frm = new Form2();
            frm.Show(this);
            Control.CheckForIllegalCrossThreadCalls = true;
            Application.Run(frm);
        });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
    }

知道这是否100%安全,可能有一个Winforms交互搞砸了。你在这里没有经过测试的水域,感染了鲨鱼。

答案 1 :(得分:3)

需要在UI线程上创建

B

您仍然可以使用B从辅助线程与Control.Invoke进行互动。

答案 2 :(得分:2)

如果你实际上在不同的线程上运行了两个消息循环,那么就没有办法完成你所追求的了。如果您希望W拥有B,则必须在主要帖子上创建B,并InvokeB进行所有互动第二个主题。