Reputation: 15847
I have a form that is used like a dialog, to be sure that the dialog get the correct parent the following method is used :
this.ShowDialog(myForm);
The problem is that this(my dialog form) and myForm is created on diffrent threads and when calling ShowDialog a crossthread exception will be thrown.
this.InvokeRequired = false
myForm.InvokeRequired = true
How do I handle this? Do I have to make sure that both are created on the same UI thread?
Upvotes: 2
Views: 8106
Reputation: 21
This is working for me - this code is in the "Parent" Form which is running on the main thread and the child form is running from another thread, the Parent form is passed in as a parameter to the other thread as it has previously been opened on the main thread:
In the Parent Form on the main thread:
public delegate void ShowChildConsumer(Form ChildForm);
public void ShowChild(Form ChildForm)
{
if (this.InvokeRequired)
{
var d = new ShowChildConsumer(ShowChild);
this.Invoke(d, new object[] { ChildForm });
}
else
ChildForm.ShowDialog(this);
}
In the other thread:
frmChildForm childform = new frmChildForm();
parentform.ShowChild(childform);
result = childform.DialogResult;
childform.Dispose();
What is interesting is that even though the ShowDialog is called on the main thread - I can create and access the form from the other thread!
Hope that helps
Upvotes: 0
Reputation: 2751
Chris has suggested the right approach but as long as you are where you are now, you can try this:
public void ShowMe()
{
if (_myForm.InvokeRequired)
_myForm.Invoke(new MethodInvoker(ShowMe));
else
this.ShowDialog(_myForm);
}
If the above doesnt work then pass the SynchronizationContext from your parent form to the class that is performing ShowDialog and perform Invoke on that.
http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx
On a related note, you might want to have a relook at your design. Seems pretty convoluted.
Upvotes: 1
Reputation: 7496
Sample code with self-explanatory variables:
var logicToInvokeInsideUIThread = new MethodInvoker(() =>
{
// ...
ShowDialog(this);
// ...
};
if (InvokeRequired)
{
Invoke(logicToInvokeInsideUIThread);
}
else
{
logicToInvokeInsideUIThread.Invoke();
}
I guess this is the better code logic to handle such cases. Sometimes Invoke()
isn't needed.
Upvotes: 1
Reputation: 137188
You have to ensure that all forms are created on the UI thread.
So rather than create the form on your background thread, pass a message to the UI thread to tell it to create and display the form.
Upvotes: 3