C# 更新UI线程控件时,会命中非调用所需路径

C# 更新UI线程控件时,会命中非调用所需路径,c#,multithreading,invokerequired,C#,Multithreading,Invokerequired,我有以下Windows窗体代码: public partial class Form1 : Form { public Form1() { InitializeComponent(); new Thread(SampleFunction).Start(); } void SampleFunction() { for (int i = 0; i < 10; i++) {

我有以下Windows窗体代码:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        new Thread(SampleFunction).Start();
    }

    void SampleFunction()
    {
        for (int i = 0; i < 10; i++)
        {
            if (textBox1.InvokeRequired == true)
                textBox1.Invoke((MethodInvoker)delegate { textBox1.Text += "HI. "; });
            else
                textBox1.Text += "HII. "; // Sometimes hit on first pass of the loop.
            Thread.Sleep(1000);
        }
    }
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
新线程(SampleFunction.Start();
}
void SampleFunction()
{
对于(int i=0;i<10;i++)
{
if(textBox1.InvokeRequired==true)
textBox1.Invoke((MethodInvoker)委托{textBox1.Text+=“HI.”;});
其他的
textBox1.Text+=“HII.”;//有时在循环的第一个过程中命中。
睡眠(1000);
}
}

当使用断点调试上述代码时,我注意到非调用所需路径在第一次运行时被命中,但大约每10次运行一次。我感到惊讶,因为代码位于单独的线程上,我希望
invokererequired
始终为真。有人能解释一下吗?

这很可能发生因为您在窗体的构造函数中启动了线程。此时窗体尚未显示,并且在执行第一次迭代时可能尚未创建其窗口句柄

从:

如果控件的句柄尚不存在,InvokeRequested将向上搜索控件的父链,直到找到具有窗口句柄的控件或窗体。如果找不到合适的句柄,InvokeRequested方法将返回false

[……]

一种解决方案是在启动后台线程之前等待窗体句柄的创建。可以通过调用handle属性强制创建句柄,也可以等到Load事件启动后台进程

因此,在我看来,您有两个选项。1)等待,直到通过选中以下选项创建句柄:


正如您所见,我访问的是
而不是
textBox1
。我建议您在检查和调用时也这样做,因为
Control.Invoke()
将查找绝对父项(表单)无论如何。

我很欣赏这样一个完整的答案。这不公平,它会得到与普通答案相同的分数。@Sabuncu:很高兴我能帮忙,谢谢!我没想到你会觉得它这么完整。:)这是一个高质量的答案。
for (int i = 0; i < 10; i++)
{
    while (!this.IsHandleCreated) { Thread.Sleep(25); }

    ...
}
for (int i = 0; i < 10; i++)
{
    while (this.Handle == IntPtr.Zero) { Thread.Sleep(25); }

    ...
}