WinForms表单冻结

5
在一个表单(F1)上,我有一个按钮,如果我从这个按钮创建另一个表单(我们称之为F2)并显示它,那么没有问题。
但是我想做这样的事情:
我的应用程序中有一个线程正在运行连接,并监听来自服务器的消息。当一条消息到达时,我的主要表单将被注册以获取运行函数的事件。从该函数中,我尝试创建并显示F2类型的表单(空白,未修改任何内容):它会显示,但然后冻结我的应用程序。
更确切地说:
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        ConnectionManagerThread.getResponseListener().MessageReceived += Form1_OnMessageReceived;
    }

    private void Form1_OnMessageReceived(object sender, MessageEventArgs e) {
        Form2 f2 = new Form2();
        f2.Show();
    }
}

你尝试过捕捉那些你认为会导致程序冻结的代码行吗? - Terry
冻结发生在f2.Show()之后。没有错误,也没有异常发生。我猜问题可能是因为该窗体实际上是从另一个线程启动的。 - Andrei S
form2也被冻结了吗,还是只有form1? - Paolo
在这种情况下,我猜测form2不是从UI线程创建的,因此没有关联的消息泵。 @Ram的回答可能会是解决方案(一旦您调试好它:)) - Paolo
2个回答

7

我认为原因是您正在执行跨线程操作。在创建form2之前,您需要将表单的创建放在UI线程上。以下内容可能会对您有所帮助:

  public delegate void ShowForm(object sender, MessageEventArgs e);
  public partial class Form1 : Form
  {
     public Form1()
     {
        InitializeComponent();
        ConnectionManagerThread.getResponseListener().MessageReceived += Form1_OnMessageReceived;
     }

     private void Form1_OnMessageReceived(object sender, MessageEventArgs e)
     {
         if (this.InvokeRequired)
         {
            this.BeginInvoke(new ShowForm((Form1_OnMessageReceived), new object[] { sender, e }));
         }
         else
         {
            Form2 f2 = new Form2();
            f2.Show();
         }
      }
  }

我认为“this.BeginInvoke(new ShowForm(new object[] { sender, e }));”这行代码存在问题,它显示“错误 CS0149:需要方法名”。 - Andrei S
@andrew - 现在检查一下,我忘记放目标名称了 :). - Ram

2

使用Ram的代码,我终于做到了并且它有效。

谢谢!

public delegate void ShowForm(object sender, MessageEventArgs e);

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        ConnectionManagerThread.getResponseListener().MessageReceived += Form1_OnMessageReceived;
    }

     private void Form1_OnMessageReceived(object sender, MessageEventArgs e)
     {
         ShowForm2(sender, e);
     }

    private void ShowForm2(object sender, MessageEventArgs e)
    {
        if (this.InvokeRequired)
        {
            ShowForm f = new ShowForm(ShowForm2);
            this.Invoke(f, new object[] { sender, e });
        }
        else
        {
            Form2 f2 = new Form2();
            f2.Show();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接