Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 更改线程中的标签属性_C#_Multithreading - Fatal编程技术网

C# 更改线程中的标签属性

C# 更改线程中的标签属性,c#,multithreading,C#,Multithreading,我正在为程序的某个特定部分编写功能,该部分要求我连续更改窗口上多个标签的文本,直到用户按下按钮为止。我创建了一个线程来完成此任务,并很快注意到运行时抱怨跨线程访问标签,并给出错误消息: 跨线程操作无效:从创建控件“label2”的线程以外的线程访问控件“label2” 后来我了解到,不允许在UI线程以外的线程中访问System.Windows.Forms.Control成员。但是,我的问题与以下简化代码有关: private void myThread(){ //'labels' is an a

我正在为程序的某个特定部分编写功能,该部分要求我连续更改窗口上多个标签的文本,直到用户按下按钮为止。我创建了一个线程来完成此任务,并很快注意到运行时抱怨跨线程访问标签,并给出错误消息:

跨线程操作无效:从创建控件“label2”的线程以外的线程访问控件“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线程之外的线程中更改标签的某些属性,而其他属性则是禁止的呢?我是否遗漏了一些更大的概念?非常感谢您的帮助。

UI组件只能在主UI线程上访问。因此,由于多线程的行为,正在系统上创建一个新线程。这样,主UI的线程就不会被阻塞。也就是说,如果要访问控件,需要根据条件调用
Invoke
BeginInvoke
方法

样本:

Label1.BeginInvoke((Action) (() => { \\Multiple Line of codes here. }));
此外,请查看以下链接:

补充说明:虽然在某些情况下可以不使用
调用
方法,但它仍然比sorry更安全。有些可能最终在运行时抛出此类异常。根据程序运行时的情况而定

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

那么,为什么我能够在UI线程之外的线程中更改标签的某些属性,而其他属性则是禁止的呢

可能性包括:

  • 因为有人忘了添加交叉线程检查
  • 更改该属性不会触发UI线程所需的某些代码
  • 有人忘了添加跨线程检查,更改该属性会触发UI线程所需的一些代码,但幸运的是,这次程序没有崩溃

  • 由于2和3在99%的时间里是无法区分的,你可能会认为你处于情境2,而实际上你处于情境3。这意味着你无法复制随机崩溃。

    currLabel.BackColor=Color.Yellow这可以从非UI线程完成吗?你完全没有回答这个问题。有时,您可以从后台线程编辑控件的属性,即使您不应该这样做。虽然这是可能的,但它仍然比“抱歉”更安全。有些可能最终在运行时抛出此类异常。视情况而定,程序运行时间是,所以把这个评论放在你答案的顶部,它会比我的好。好的,我昨天已经添加了它。不能同时通知所有人。isp问题:):DNice命中,涵盖了大多数可能性。另请参阅。简短版本:您可能不会总是得到异常,特别是在没有在调试器下运行的情况下,但是您不能指望从拥有UI对象的线程以外的线程安全地访问UI对象。(在某些情况下,你可以侥幸逃脱,但不值得尝试编写代码来绕开这些情况……只要始终确保你调用的是UI线程。)@PeterDuniho是否曾经有过这样的情况:当UI线程可用/不忙时,正在执行的任务/工作实际上是在UI线程上执行的,因此不会引发异常?当然,当我开始编写UI时,我多次看到这个问题,并且总是对此感到疑惑。似乎有50%的时间我都能侥幸逃脱。@khargoosh:默认的任务调度程序永远不会使用UI线程来执行工作。当然,如果您编写自己的调度程序并使用它,那么所有的赌注都没有了。您自己的调度程序可以做任何它想做的事情。但是没有一个头脑正常的人会编写一个任务调度器来调度UI线程上的工作。