【问题标题】:Cross thread operation跨线程操作
【发布时间】:2013-02-05 09:49:51
【问题描述】:

谁能告诉我 if 和 else 语句在这个函数中是如何相关的。我正在将来自另一个线程的文本显示到 GUI 线程。执行的顺序或方式是什么。 else语句有必要吗?

delegate void SetTextCallback(string text);

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the
        // calling thread to the thread ID of the creating thread.
        // If these threads are different, it returns true.
        if (this.textBox7.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.textBox7.Text = text;
        }
    }

【问题讨论】:

  • 如果没有你的else,程序很可能会崩溃,这是因为你无法从外部线程更改GUI。由于无论如何您都需要更改 GUI,因此您可以使用 Invoke 方法来代替。如果没有else,外部线程将在调用该方法后立即尝试更改 GUI(导致我之前提到的崩溃)。 InvokeRequired 检查对象是否属于当前线程,基本上意味着this.textBox7.Text = text; 永远不会在textBox7 所属线程之外的任何线程上运行。

标签: c# multithreading


【解决方案1】:
  1. 另一个线程调用SetText
  2. 由于创建表单的不是线程,它需要Invoke
  3. this.Invoke 再次使用给定参数调用 SetText。另请查看this
  4. 现在从 UI 线程调用 SetText,无需调用
  5. else 块中,我们确定文本已安全设置线程

【讨论】:

  • 谢谢,真的很有帮助!
【解决方案2】:

InvokeRequired 用于检查语句是在主 UI 线程中执行,还是在 UI 线程以外的其他线程中执行。

如果语句在 UI 线程之外的其他线程中执行,则使用 Invoke 不会导致任何 CrossThread 异常。

【讨论】:

  • 谢谢,真的很有帮助!
【解决方案3】:

else 绝对是必要的。

这段代码的作用是让您可以从任何线程安全地调用SetText。如果您从 UI 线程(if 块)以外的线程调用它,它会透明地将调用转发到 UI 线程(else 块),这是唯一可以访问控件以读取或设置其文本的线程.

如果没有在 UI 线程上完成,盲目地寻找this.textBox7.Text 将导致异常。

【讨论】:

  • 谢谢,真的很有帮助!
【解决方案4】:

只是为了补充其他答案,这是一种常见模式(尤其是在被调用方法包含大量逻辑的情况下)-如果InvokeRequired 返回 true,则从 UI 线程回调到同一方法:

private void SetText(string text)
{
    if (InvokeRequired)
        BeginInvoke(new Action<string>((t) => SetText(text)));
    else
        textBox7.Text = text;
}

这样您就不必在ifelse 中重复您的逻辑。

【讨论】:

  • 谢谢,真的很有帮助!
猜你喜欢
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多