【问题标题】:Cross-thread operation跨线程操作
【发布时间】:2015-04-10 04:17:04
【问题描述】:

我正在线程中做一些事情,我正在尝试访问标签属性,但我无法设置属性值。

lblDisplay.Visible = true;

我在这方面遇到了错误。 错误 - 跨线程操作无效:控件“lblDisplay”从创建它的线程以外的线程访问。 提前致谢。

【问题讨论】:

  • 你需要使用Invoke
  • @karthiga:有很多帖子可以回答您的问题。下次发问题前先在ST内部搜索一下。

标签: c# multithreading winforms


【解决方案1】:

您应该使用表单上的BeginInvoke 方法将变量设置在其运行所在的同一线程上,例如:

this.BeginInvoke((Action)delegate{ lblDisplay.Visible = true; });

大多数人会告诉您改用Invoke 方法,但除非您绝对需要在执行线程中的任何其他代码之前运行委托中的所有内容,否则您可能不需要它。 Invoke 将阻止线程继续处理,直到委托完成,而 BeginInvoke 将简单地在表单正在运行的线程中执行它,同时运行开始调用的线程。

【讨论】:

    【解决方案2】:

    我认为您首先需要检查它是否需要调用(在其他情况下,相同的代码可能不需要调用)所以...

    if(lblDisplay.InvokeRequired) {
     lblDisplay.Invoke((Action)delegate{ lblDisplay.Visible = true; }); // For synchronous
     lblDisplay.BeginInvoke((Action)delegate{ lblDisplay.Visible = true; }) // For asynchronous
          }
    else
    {
    lblDisplay.Visible=true;
    }
    

    【讨论】:

      【解决方案3】:

      您不能直接从创建它的线程以外的线程访问。您可以使用 MethodInvoker 设置该属性值。

      lblDisplay.Invoke((MethodInvoker)(() => { lblDisplay.Visible = true; }));
      

      这是您需要在不同线程中访问控件的方式。

      【讨论】:

        【解决方案4】:

        Control 只能在创建它的线程(即 UI 线程)中访问。

        试试这个,

        Invoke(new Action(() =>
        {
            lblDisplay.Visible = true;
        }));
        

        【讨论】:

          【解决方案5】:

          this.BeginInvoke 方法与 lambda 一起使用:

          this.BeginInvoke(new Action(() => { lblDisplay.Visible = true; }));
          

          参考:https://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke(v=vs.110).aspx

          【讨论】: