Reputation: 753
I'm experiencing something weird. I can access many of my form's controls from within my BackgroundWorker DoWork
method, but trying to get the Handle
property on any of them will give me "Cross-thread operation not valid".
For example:
private void backgroundWorker1_DoWork(object sender,
System.ComponentModel.DoWorkEventArgs e)
{
var usefulText = textbox1.Text;
var formName = this.Name;
var formHandle = this.Handle; // this line won't work
}
Why is it that I can access some of the Properties except for the Handle
one (or so it seems)?
Upvotes: 0
Views: 220
Reputation: 70701
The "Cross-thread operation not valid" InvalidOperationException
is the norm. I have found that for reasons unknown to me, some controls have members that can be successfully called from the wrong thread, but the documentation is very clear about which ones are expected to work:
In addition to the InvokeRequired property, there are four methods on a control that are thread safe to call: Invoke, BeginInvoke, EndInvoke and CreateGraphics
In other words, the real mystery in your question isn't why you get an exception trying to call the Handle
property getter. It's why you don't get an exception calling the Text
or Name
getters.
Personally, I find that mystery less interesting. The bottom line is that if you need to retrieve the Handle
property in your DoWork
event handler, you will need to use the Control.Invoke()
method to access the property on the UI thread and return it back to your code in the worker thread. Alternatively, retrieve the handle value before starting the worker, and make it available to the DoWork
event handler via the mechanism of your choice.
EDIT:
Even though I don't find the mystery all that interesting, I did go ahead and look at the referencesource.microsoft.com web site, and I can see that the Text
property is handled as an explicit exception to the "no cross-thread calls" rule. There's even a comment that reads "it's okay to call GetWindowText cross-thread", and the code there (in the internal WindowText
property) uses the MultithreadSafeCallScope
class to disable the cross-thread check for the duration of the operaton.
It would be nice if this were better-documented (i.e. on MSDN itself), but there you go. :)
Upvotes: 4