C#打开一个表单,然后从另一个方法关闭它

时间:2012-07-08 20:48:08

标签: c# winforms multithreading

我对C#很陌生,对某些事情有点小问题。我认为线程可能就是答案,但这只是我在寻找解决方案时所采用的Buzz-Word。

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();
        }
}

这只是我的剥离应用程序的快速代码片段,但是在尝试这个时我得到一个错误:跨线程操作无效:控制'Form2'从一个线程访问,而不是创建它的线程。< / p>

另外作为旁注,我使用的是form2.TopMost = true;尝试在其他所有内容上打开窗口,但这通常最终落在Visual Studio等后面

3 个答案:

答案 0 :(得分:3)

您需要使用Invoke才能使用其他主题中的表单。

这是一篇很好的文章,解释了如何使用多个线程的Windows窗体控件:How to: Make Thread-Safe Calls to Windows Forms Controls

试试这个:

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();
            }
        }
    }
}

答案 1 :(得分:1)

您可以通过以下方式修改runCheckFalse方法 - 这是Windows窗体的一个相当标准的模式:

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

实际上,这样做是检查我们是否在GUI线程上运行(“如果InvokeRequired”)。如果我们不是,我们在GUI线程上调用自己并立即返回。如果我们在GUI线程上运行,那么我们不需要做任何事情,只需继续正常的方法。

如果您需要使用参数:

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

答案 2 :(得分:0)

WinForm控件只能从UI线程更新。 Take a look at this blog post,它提供了许多方法来确保更新发生在UI线程上。这是一个很长的帖子,但值得一读。如果您没有时间阅读它,那么快速而肮脏的方法是第一个。

埃里克