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

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

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

 b.Owner = w; 

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

所以我试图通过在W上使用Control.Invoke在主UI线程上执行代码。 但是,我得到了同样的错误,告诉我我正在尝试从错误的线程访问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 

我该怎么做呢?

这是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交互,搞砸了。 你在这里没有经过考验的水域,被鲨鱼肆虐。

需要在UI线程上创建B

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

如果你实际上在不同的线程上运行了两个消息循环,那么就没有办法做你想要的了。 如果你想要W拥有B ,你将不得不在主线程上创建B并从第二个线程InvokeB所有交互。