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

Pie*_*aud 7 c# invoke winforms

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

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

b.Owner = w;
Run Code Online (Sandbox Code Playgroud)

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

于是,我就用主UI线程上执行代码,Control.InvokeW.但是,我得到同样的错误,告诉我我正在尝试B从错误的线程访问:

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
Run Code Online (Sandbox Code Playgroud)

我该怎么做呢?

Han*_*ant 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();
    }
Run Code Online (Sandbox Code Playgroud)

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

  • 您是否了解了上述方法的安全性?我想这样做(有一个表单拥有一个绑定到不同线程的表单)但是看到两个问题:(1)显示另一个所拥有的表单将调用`Owner.AddOwnedForm`,这可能不是线程 - 安全; 最好在所有者表单的主题上执行操作; (2)如果绑定到不同线程的两个表单尝试同时显示自己,可以在另一个设置为false的时间和执行要求它为false的操作的时间之间设置`CheckForIllegalCrossThreadCalls = true`. (2认同)