更改线程

时间:2016-09-20 04:24:27

标签: c# multithreading

我正在为程序的特定部分编写功能,这要求我不断更改窗口上多个标签的文本,直到用户按下按钮。我已经创建了一个线程来实现这一点,并很快注意到运行时抱怨标签的跨线程访问,并给出错误消息:

  

跨线程操作无效:控制' label2'从创建它的线程以外的线程访问。

我自从了解到不允许访问UI线程以外的线程中的System.Windows.Forms.Control成员。但是,我的问题与以下简化代码有关:

private void myThread(){
//'labels' is an array of all labels on my form
Label currLabel = labels[rand.Next(0, labels.Length)];

currLabel.BackColor = Color.Yellow; //This works with no complaint from the runtime
currLabel.Text = "Hello"; //This causes the previously-mentioned error
}

那么,为什么我能够在UI线程以外的线程中更改标签的某些属性,但其他的只是禁止?我在这里错过了一些更大的概念吗?任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

只能在主UI线程上访问UI组件。因此,正如多线程行为一样,在系统上创建一个新线程。通过这样做,主UI的线程不会被阻止。话虽这么说,如果你想访问控件,你需要调用InvokeBeginInvoke方法,具体取决于条件

样品:

Label1.BeginInvoke((Action) (() => { \\Multiple Line of codes here. }));

另外,请检查以下链接:

Accessing UI Control from BackgroundWorker Thread

Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on

Solve a cross-threading Exception in WinForms

添加注意:虽然在某些时候可能不使用Invoke方法,但它仍然比抱歉更安全。有些人最终可能会在运行时抛出此类异常取决于程序运行的情况

  

对Windows窗体控件的访问本质上不是线程安全的。如果有两个或多个线程操纵控件的状态,则可以强制控件进入不一致状态。其他与线程相关的错误也是可能的,例如竞争条件和死锁。确保以线程安全的方式访问控件非常重要。

答案 1 :(得分:1)

  

那么,为什么我能够在UI线程以外的线程中更改标签的某些属性,但其他线程只是禁止?

可能性包括:

  1. 因为有人忘记添加跨线程检查
  2. 更改该属性不会触发UI线程所需的某些代码。
  3. 有人忘记添加跨线程检查并更改该属性会触发UI线程所需的一些代码,但是你很幸运,这次程序没有崩溃。
  4. 由于2%和3在99%的时间内无法区分,因此当你处于情境3时,你可能会认为你处于情境2中。这意味着你无法重现的随机崩溃。