-1

I'm writing the functionality for a particular part of a program which requires me to change the text of a number of labels on a window continuously until the user presses a button. I've created a thread to accomplish this, and quickly noticed that the runtime complains about cross-thread accessing of a label, giving the error message:

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

I've since learned that accessing a System.Windows.Forms.Control member in a thread other than the UI thread is not allowed. However, my question has to do with the following simplified code:

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
}

So, why am I able to change some properties of labels in a thread other than the UI thread, but others are just off-limits? Am I missing some larger concept here? Any help is appreciated.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
AustinC
  • 169
  • 2
  • 7
  • See also https://stackoverflow.com/questions/32603127/how-can-a-control-property-be-modified-from-background-thread-without-control-in. Short version: you may not always get the exception, especially if not running under the debugger, but you cannot count on safely accessing UI objects from other than the thread that owns them. (There are corner cases where you can get away with it, but it's not worth trying to code around those...just always make sure you are invoking to the UI thread.) – Peter Duniho Sep 20 '16 at 04:36
  • @PeterDuniho is it ever the case that the task/work being executed is actually executed on the UI thread, when the UI thread is available/not-busy, thus not raising the exception? Of course I saw this issue many times when I started coding UI, and always wondered this. It seemed I could get away with it maybe 50% of the time. – khargoosh Sep 20 '16 at 04:41
  • 2
    @khargoosh: the default task scheduler will never use the UI thread to perform work. Of course, if you write your own scheduler and use that, all bets are off. Your own scheduler can do whatever it wants. But nobody in their right mind would write a task scheduler that would schedule work on the UI thread. – Peter Duniho Sep 20 '16 at 04:44

2 Answers2

1

UI Components can only be accessed on the Main UI Thread. Therefore, as Multi-threading behaves, is creating a new thread on your system. By doing so, the Main UI's thread is not blocked. That being said, if you want to access the Controls, you need to call Invoke or BeginInvoke Methods, depending on the condition

sample:

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

Also, check on these links:

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

ADDED NOTE: while it is possible not to use Invoke Methods at some point, it is still better safe than sorry. some may eventually throw such exceptions on runtime. depending on the situation the program is running at

Access to Windows Forms controls is not inherently thread safe. If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state. Other thread-related bugs are possible, such as race conditions and deadlocks. It is important to make sure that access to your controls is performed in a thread-safe way.

Community
  • 1
  • 1
TheQuestioner
  • 702
  • 10
  • 28
1

So, why am I able to change SOME attributes of labels in a thread other than the UI thread, but others are just off-limits?

Possibilities include:

  1. Because someone forgot to add the cross-thread check
  2. Changing that attribute doesn't happen to trigger some piece of code that required to UI thread.
  3. Someone forgot to add the cross-thread check and changing that attribute triggers some piece of code that required to UI thread, but you got lucky and the program didn't crash this time.

Since 2 and 3 are indistinguishable 99% of the time, you may think that you are in situation 2 when really you are in situation 3. Which means random crashes that you can't reproduce.

Jonathan Allen
  • 68,373
  • 70
  • 259
  • 447