The great work around is to invoke the control. For instance, I use the following method to update a richTextBox control from any thread I happen to be in:
public void UpdateRichTextBoxStatus(string value)
{
if (InvokeRequired)
{
// We're not in the UI thread, so we need to call Invoke
Invoke(new StringParameterDelegate(UpdateRichTextBoxStatus), new object[] { value });
return;
}
// Must be on the UI thread if we've got this far
richTextBoxStatus.Text = value + richTextBoxStatus.Text;
}
It checks to see if the control needs invoking (to avoid the cross-thread exception). If it does, it will reursively call itself again using a delegate and then update the richTextBox.
This worked fine and dandy most of the time. However, I had one condition where different invocations were happening at the same time, on different controls, but being invoked from an external, managed DLL. What happened is the invoke occured, but then the whole program hung on a call to the DLL.
Further investigation (god bless the parallel stacks threading debugging view) showed that one of the invocations went into a sleep state, waiting for the other invocation to finish. The Invoke call itself is synchronous, so the next invoke call was waiting for the original to finish. And hence the program just hung there. Waiting... waiting... never finishing.
Well there's an easy workaround for this. Instead of calling Invoke, call BeginInvoke! This makes the call asynchronous. The function thus becomes:
public delegate void StringParameterDelegate(string value);
public void UpdateRichTextBoxStatus(string value)
{
if (InvokeRequired)
{
// We're not in the UI thread, so we need to call BeginInvoke
BeginInvoke(new StringParameterDelegate(UpdateRichTextBoxStatus), new object[] { value });
return;
}
// Must be on the UI thread if we've got this far
richTextBoxStatus.Text = value + richTextBoxStatus.Text;
}
Thanks this works Great!!. I was stuck badly..
ReplyDelete