Banshee
Banshee

Reputation: 15847

Use ShowDialog(form) where form is created on another thread?

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

Answers (4)

Andrew
Andrew

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

bobbyalex
bobbyalex

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

Joao
Joao

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

ChrisF
ChrisF

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

Related Questions