Reputation: 3969
It seems a random chance that I will get a cross thread exception upon execution of my win forms application. Here's how I'm trying to manage it:
private void ToOutput(string s)
{
if (!this.IsHandleCreated)
this.CreateHandle();
if (FormOutputArea.InvokeRequired)
{
FormOutputArea.Invoke(new Action(delegate ()
{
FormOutputArea.AppendText(s + Environment.NewLine);
}));
}
else
{
FormOutputArea.AppendText(s + Environment.NewLine);
}
}
It appears InvokeRequired
is not always accurate. I tried BeginInvoke
with the same result.
EDIT: Even when I check IsHandleCreated
and InvokeRequired
using breakpoints they are set to true, yet the else
branch of the condition is executed.
Here's a screenshot showing where the exception is now thrown:
Upvotes: 2
Views: 169
Reputation: 941605
Putting CreateHandle() and InvokeRequired in the same method is fundamentally wrong. This will explode when the handle isn't created yet, you will create the native window on the wrong thread. A child control's window must be owned by the same thread that owns the form and that thread must pump a message loop (Application.Run).
The simple workaround is to ensure that the thread will not be started until the form's window is created. Which will also create the windows of all the controls embedded in that form. The earliest that happens is in the form's Load event. At that point you can trust InvokeRequired to be accurate.
And beware of trouble when the user closes the form, your original code will behave very poorly if you allow the thread to continue running. It is not yet clear whether you bomb the code before the form's window is created or after it is closed. You must ensure that the thread has either stopped or cannot call ToOutput() anymore. The subject of this answer.
Upvotes: 5