Matt Clements
Matt Clements

Reputation: 197

C# Opening a Form, then closing it from another method

I am pretty new to C# and having a little issue with something. I believe threading may be the answer, but thats just a Buzz-Word I have picked up when looking for solutions.

namespace Test
{
    public partial class Form1 : Form
    {
        private Form2 form2;

        public Form1()
        {
            InitializeComponent();
            form2 = new Form2();
        }

        private void runCheck(object source, System.Timers.ElapsedEventArgs e)
        {
            form2.ShowDialog();
            form2.TopMost = true;
        }

        private void runCheckFalse()
        {
            form2.Hide();
        }
}

This is only a quick code snippet of my stripped out application, however when trying this I get an error: Cross-thread operation not valid: Control 'Form2' accessed from a thread other than the thread it was created on.

Also as a side note I am using form2.TopMost = true; to attempt to open the window on top of everything else, but this often ends up at the back behind Visual Studio etc

Upvotes: 1

Views: 2637

Answers (3)

dash
dash

Reputation: 91462

You can modify your runCheckFalse method in the following way - this is a fairly standard pattern for Windows Forms:

private void runCheckFalse()      
{       
    if(InvokeRequired)
      {
            BeginInvoke(new MethodInvoker(runCheckFalse));
            return;
      }                    
    form2.Hide();  
}

Effectively, what this does is check to see if we are running on the GUI thread (" if InvokeRequired"). If we aren't, we call ourselves on the GUI thread and immediately return. If we are running on the GUI thread, then we don't need to do anything and just continue with the method as normal.

If you need to use parameters:

private void runCheckFalse(bool someParameter)      
{       
    if(InvokeRequired)
      {
            BeginInvoke(new MethodInvoker(() => { runCheckFalse(someParameter);}));
            return;
      }                    
    form2.Hide();  
}

Upvotes: 1

Ove
Ove

Reputation: 6317

You need to use Invoke in order to work with the form from a different thread.

Here is a nice article explaining how to work with Windows Forms controls from multiple threads: How to: Make Thread-Safe Calls to Windows Forms Controls

Try this:

namespace Test
{
    public partial class Form1 : Form
    {
        private Form2 form2;

        public Form1()
        {
            InitializeComponent();
            form2 = new Form2();
        }

        private void runCheck(object source, System.Timers.ElapsedEventArgs e)
        {
            if (form2.InvokeRequired)
            {
                form2.Invoke(new EventHandler(delegate { form2.ShowDialog(); form2.TopMost = true; }));
            }
            else
            {
                form2.ShowDialog(); 
                form2.TopMost = true;
            }
        }

        private void runCheckFalse()
        {
            if(form2.InvokeRequired)
            {
                form2.Invoke(new EventHandler(delegate { form2.Hide(); }));
            }
            else
            {
                form2.Hide();
            }
        }
    }
}

Upvotes: 5

Erick T
Erick T

Reputation: 7429

WinForm controls can only be updated from the UI thread. Take a look at this blog post, it gives a number of approaches to making sure that the update occurs on the UI thread. It is a long post, but worth the read. The quick and dirty approach is the first one if you don't have time to read it.

Erick

Upvotes: 0

Related Questions