Search code examples
c#winformsinvokemultithreadingshowdialog

What's wrong with my cross-thread call in Windows Forms?


I encounter a problem with a Windows Forms application.

A form must be displayed from another thread. So in the form class, I have the following code:

private delegate void DisplayDialogCallback();

public void DisplayDialog()
{
    if (this.InvokeRequired)
    {
        this.Invoke(new DisplayDialogCallback(DisplayDialog));
    }
    else
    {
        this.ShowDialog();
    }
}

Now, every time I run this, an InvalidOperationException is thrown on the line this.ShowDialog();:

"Cross-thread operation not valid: Control 'SampleForm' accessed from a thread other than the thread it was created on."

What's wrong with this piece of code? Isn't it a valid way to make cross-thread calls? Is there something special with ShowDialog()?


Solution

  • Try this one:

    private delegate void DisplayDialogCallback();
    
    public void DisplayDialog()
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new DisplayDialogCallback(DisplayDialog));
        }
        else
        {
            if (this.Handle != (IntPtr)0) // you can also use: this.IsHandleCreated
            {
                this.ShowDialog();
    
                if (this.CanFocus)
                {
                    this.Focus();
                }
            }
            else
            {
                // Handle the error
            }
        }
    }
    

    Please note that InvokeRequired returns

    true if the control's Handle was created on a different thread than the calling thread (indicating that you must make calls to the control through an invoke method); otherwise, false.

    and therefore, if the control has not been created, the return value will be false!