在执行我的win表单应用程序时,我似乎有机会得到一个跨线程异常。以下是我试图管理它的方法:
private void ToOutput(string s)
{
if (!this.IsHandleCreated)
this.CreateHandle();
if (FormOutputArea.InvokeRequired)
{
FormOutputArea.Invoke(new Action(delegate ()
{
FormOutputArea.AppendText(s + Environment.NewLine);
}));
}
else
{
FormOutputArea.AppendText(s + Environment.NewLine);
}
}
似乎InvokeRequired
并不总是准确的。我尝试了BeginInvoke
同样的结果。
编辑:即使我使用断点检查IsHandleCreated
和InvokeRequired
,它们也会设置为true,但条件的else
分支会被执行。< / p>
这是一个屏幕截图,显示了现在抛出异常的位置:
答案 0 :(得分:5)
将CreateHandle()和InvokeRequired放在同一个方法中是根本错误的。当手柄尚未创建时,这将会爆炸,您将在错误的线程上创建本机窗口。子控件的窗口必须由拥有该表单的同一个线程拥有,并且该线程必须泵送一个消息循环(Application.Run)。
简单的解决方法是确保在创建表单窗口之前不会启动该线程。这也将创建嵌入在该表单中的所有控件的窗口。最早发生的是表单的Load事件。此时,您可以信任InvokeRequired是准确的。
当用户关闭表单时要小心,如果允许线程继续运行,原始代码的行为将非常糟糕。目前尚不清楚是否在创建表单窗口之前或关闭之后炸弹代码。您必须确保线程已停止或无法再调用ToOutput()。 this answer的主题。