0

我对 C# 还很陌生,并且遇到了一些问题。我相信线程可能是答案,但这只是我在寻找解决方案时听到的流行语。

命名空间测试
{
    公共部分类Form1:表格
    {
        私人表格2表格2;

        公共表格1()
        {
            初始化组件();
            表格 2 = 新表格 2();
        }

        私人无效运行检查(对象源,System.Timers.ElapsedEventArgs e)
        {
            form2.ShowDialog();
            form2.TopMost = true;
        }

        私人无效runCheckFalse()
        {
            form2.Hide();
        }
}

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

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

4

3 回答 3

4

您需要使用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();
            }
        }
    }
}
于 2012-07-08T21:03:07.163 回答
1

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

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

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

如果需要使用参数:

private void runCheckFalse(bool someParameter)      
{       
    if(InvokeRequired)
      {
            BeginInvoke(new MethodInvoker(() => { runCheckFalse(someParameter);}));
            return;
      }                    
    form2.Hide();  
}
于 2012-07-08T21:10:15.517 回答
0

WinForm 控件只能从 UI 线程更新。看看这篇博文,它提供了许多方法来确保更新发生在 UI 线程上。这是一篇很长的文章,但值得一读。如果您没有时间阅读,那么快速而肮脏的方法是第一种。

埃里克

于 2012-07-08T20:55:50.850 回答