设置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
并从第二个线程Invoke
与B
所有交互。