C# calling form.show() from another thread

Viewed 64246

if I call form.show() on a WinForms object from another thread, the form will throw an exception. Is where any way I can add a new, visible form to the main app thread? Otherwise, how can I open the form without stopping my currently executing thread?

Here is my sample code. I am attempting to start a thread and then execute some work within that thread. As the work progresses, I will show the form.

public void Main()
{
    new Thread(new ThreadStart(showForm)).Start();
    // Rest of main thread goes here...
}

public void showForm() 
{
    // Do some work here.
    myForm form = new myForm();
    form.Text = "my text";
    form.Show();
    // Do some more work here
}
5 Answers

The best way by my experience:

var ac = (ReportPre)Application.OpenForms["ReportPre"];
Thread shower = new Thread(new ThreadStart(() =>
    {
        if (ac == null)
        {                
            this.Invoke((MethodInvoker)delegate () {
                ac = new ReportPre();
                ac.Show();
            });       
        }
        else
        {
            this.Invoke((MethodInvoker)delegate
            {
                pictureBox1.Visible = true;
            });
            if (ac.InvokeRequired)
            {
                ac.Invoke(new MethodInvoker(delegate {
                    ac.Hide();
                    ac.Show();
                }));                          
            }
        }
    }));
shower.Start();

If your use case is to display a GUI while the Main GUI Thread is busy (like loading bar) you can do the following:

private void MethodWithLoadingBar()
{
    Thread t1 = new Thread(ShowLoading);
    t1.Start();
    // Do the Main GUI Work Here
    t1.Abort();
}

private void ShowLoading()
{
    Thread.Sleep(1000); //Uncomment this if you want to delay the display 
                        //(So Loading Bar only shows if the Method takes longer than 1 Second)
    loadingGUI = new LoadingGUI();
    loadingGUI.label1.Text = "Try to Connect...";
    loadingGUI.ShowDialog();
}

My LoadingGUI is a simple Form with a public Label and a ProgressBar with Style set to Marquee

After searching the web and not finding a good solution, I came up with my own:

public async Task FunctionWhereIStartForm( Func<Delegate,object>invoke )
{
  //this is on another thread

 invoke( new MethodInvoker( ( ) =>
              {
                new formFoo().Show( );
              } ) );
}

Then call like this:

await FunctionWhereIStartForm(Invoke);
Related