You should familiarize yourself with the Invoke(...) and BeginInvoke(...) methods and determine what semantics you need for this cross-thread update. Do you want to fire-and-forget, and not wait for the message pump to get back around to your text update? Use BeginInvoke(...)
. Do you want the thread to block until the UI update has occurred? Use Invoke(...)
.
Also, bear in mind that if the form may potentially be disposed, or hasn't been shown yet, you need to check more than just the InvokeRequired
flag on the form before calling Invoke(...)
or BeginInvoke(...)
. If there is a potential for this case, your logic should look something like this:
public void DoSomeUpdate(string text)
{
if(this.IsDisposed || (!this.IsHandleCreated))
{
// error condition; run away!
return;
}
if(this.InvokeRequired)
{
// BeginInvoke or Invoke here, based on the semantics you need
return;
}
this.UpdateSomeLabel(text);
}
Comment please if anything here is unclear.
Update
There has been some commentary regarding checking for whether the control's handle has been created or if it has been disposed.
Regarding the former case (IsHandleCreated
), that's definitely something you can assume beforehand in many cases; however, not all cases. If you're not dynamically creating controls, and your background thread stuff is being triggered via the UI thread, you're probably safe. However...
If there's any hint of a possibility that the background thread task could be in-flight long enough for you to click the 'X' on your form and close it (thereby disposing it), then you'll get a nice exception if you don't check IsDisposed
before calling Invoke(...)
or BeginInvoke(...)
. It's similar to (in C) checking for malloc(...)
returning something non-zero. It does happen. As tedious as it is, an application author is obligated to care about these potential error cases. This does add complication; however, it's important, especially if you don't want your app to crash. Failing to properly account for IsDisposed
and IsHandleCreated
when calling Invoke(...)
or BeginInvoke(...)
exposes you to the possibility of crashing your app. You can avoid that crash with a few extra lines of code.