Why am I getting this error: "Cross-threading is not valid: lbFolders are managed from a thread other than the thread on which it was created."?

It puzzles me, maybe someone can illuminate the light of enlightenment through my ignorance. This is a Windows C # application. I am accessing the contents of a list from a stream. When I try to access it like this

prgAll.Maximum = lbFolders.SelectedItems.Count; 
I get an error. However, here is the part that I do not get. If I comment on this line, the next line
 foreach (string dir in lbFolders.SelectedItems) 
performed just fine.

Edit: As usual, my communication skills are not enough. Let me explain.

I know that accessing GUI elements from threads other than those created was causing problems. I know that the correct way to access them is through the delegate.

My question was basically this: Why can I access and iterate using the SelectedItems object just fine, but when I try to get (not set) the Count property, it explodes.

+2
multithreading c #
source share
7 answers
 prgAll.Maximum = lbFolders.SelectedItems.Count; 

On this line, you are assigning ( set / add ), which is not thread safe by default.

The second line is just a get operation, where thread safety just doesn't matter.

EDIT: I do not mean access to the prgAll element.

Access to the Count property changes the internal state of the internal ListBox, so it throws an exception.

+5
source share

You cannot access GUI elements from a separate thread. Use the delegate to make changes.

eg.

 lblStatus.Invoke((Action)(() => lblStatus.Text = counter.ToString())); 

or earlier skool:

 lblTest.Invoke((MethodInvoker)(delegate() { lblTest.Text = i.ToString(); })); 

I have a blog post on how to do this in all .Net releases here .

+16
source share

The Count property for SelectedItems is not thread safe, so you cannot use it in a cross-thread.

+3
source share

You are trying to write a control from a thread other than the main thread. Use Invoke or BeginInvoke.

 void SetMax() { if (prgAll.InvokeRequired) { prgAll.BeginInvoke(new MethodInvoker(SetMax)); return; } prgAll.Maximum = lbFolders.SelectedItems.Count; } 
+2
source share

You cannot touch a GUI object from a thread that is not the main thread of the graphical user interface. See here for more details and solutions.

+1
source share

Because you created a control in a stream, and you are trying to contact it from another. Call the InvokeRequired property, as shown here:

 private void RunMe() { if (!InvokeRequired) { myLabel.Text = "You pushed the button!"; } else { Invoke(new ThreadStart(RunMe)); } } 
+1
source share

Try the following:

 private delegate void xThreadCallBack(); private void ThreadCallBack() { if (this.InvokeRequired) { this.BeginInvoke(new xThreadCallBack(ThreadCallBack)); } else { //do what you want } } 

Although a response with a lambda expression would be sufficient.

0
source share

All Articles