C# 不可预测的跨线程异常

C# 不可预测的跨线程异常,c#,.net,multithreading,thread-safety,C#,.net,Multithreading,Thread Safety,在执行win forms应用程序时,我可能会遇到一个交叉线程异常,这似乎是随机的。以下是我试图管理它的方式: private void ToOutput(string s) { if (!this.IsHandleCreated) this.CreateHandle(); if (FormOutputArea.InvokeRequired) { FormOutputArea.Invoke(new Action(delegate ()

在执行win forms应用程序时,我可能会遇到一个交叉线程异常,这似乎是随机的。以下是我试图管理它的方式:

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);
    }
}
看来,
invokererequired
并不总是准确的。我尝试了
BeginInvoke
,得到了同样的结果

EDIT:即使我使用断点检查
IsHandleCreated
invokererequired
时,它们也被设置为true,但执行条件的
else
分支

下面是一个屏幕截图,显示异常现在抛出的位置:

将CreateHandle()和InvokeRequired放在同一个方法中根本是错误的。当句柄尚未创建时,这将爆炸,您将在错误的线程上创建本机窗口。子控件的窗口必须由拥有窗体的同一线程拥有,并且该线程必须泵送消息循环(Application.Run)

简单的解决方法是确保在创建窗体窗口之前不会启动线程。它还将创建该窗体中嵌入的所有控件的窗口。最早发生的是表单的加载事件。在这一点上,您可以信任要求准确的调用器


当用户关闭表单时要小心,如果您允许线程继续运行,您的原始代码将表现得非常糟糕。目前还不清楚是在创建窗体窗口之前还是在关闭窗体窗口之后轰炸代码。必须确保线程已停止或无法再调用ToOutput()。.

的主题您可能需要了解以下内容:即使检查已创建的控制句柄也没有帮助。我很困惑为什么连续运行五次(约20%的几率)时会抛出一次线程异常。即使我使用断点检查IsHandleCreated和InvokeRequired,它们都设置为true,但条件的else分支仍会执行。你能告诉这段代码你在这段代码中尝试了什么吗?
this
在这里指的是什么?我希望
this
会指的是这个方法所在的类。最初我使用了
FormOutputArea.IsHandleCreated
,但是当表单区域对象没有
CreateHandle
方法时,我将其更改为
this
,但没有任何效果。谢谢Hans,我想我已经解决了这个问题。我在表单的构造函数中初始化并启动了后台线程。我已经将这些移动到了_Load事件,它似乎已经对它进行了排序!谢天谢地,这个问题比我预想的要简单。