This is baffling me, maybe somebody can shine the light of education on my ignorance. This is in a C# windows app. I am accessing the contents of a listbox from a thread.
You can't access GUI elements from a separate thread. Use a delegate to make the change.
eg.
lblStatus.Invoke((Action)(() => lblStatus.Text = counter.ToString()));
or older skool:
lblTest.Invoke((MethodInvoker)(delegate()
{
lblTest.Text = i.ToString();
}));
I've got a blog post on how to do this in all the .Net releases here.
prgAll.Maximum = lbFolders.SelectedItems.Count;
On that line you perform an assignment (set/add), which by default is not thread-safe.
On the second line it's just a get operation, where thread-safety merely doesn't matter.
EDIT: I don't mean access to the prgAll element.
Accessing the Count property changes the internal state of the ListBox inner collection, that is why it throws the exception.
You're trying to write to 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;
}
Try this:
private delegate void xThreadCallBack();
private void ThreadCallBack()
{
if (this.InvokeRequired)
{
this.BeginInvoke(new xThreadCallBack(ThreadCallBack));
}
else
{
//do what you want
}
}
Though, the answer with the lambda expression would suffice.
You can't touch a GUI object from a thread that isn't the main GUI thread. See here for more details and the solution.
The Count property of SelectedItems is not thread-safe, so you can't use it cross-thread.