关闭表单在另一个线程中打开

时间:2015-04-08 20:23:28

标签: c# multithreading winforms

我的Winforms C#应用程序遇到了一些麻烦。 我希望在主线程中的某些操作完成后,将名为Popup的表单关闭。问题是由跨线程表单关闭引起的异常。

private void loginButton_Click(object sender, EventArgs e)
{
    LoginProcess.Start();    // Running Form.show() in new thread
    ActiveAcc.IsValid = false;
    ActiveAcc.Username = userBox.Text;

    try
    {
        LoginCheck(userBox.Text, passBox.Text);
    }
    catch (IOException)
    {
        MessageBox.Show("..");
        return;
    }
    catch (SocketException)
    {
        MessageBox.Show("..");
        return;
    }

    if (ActiveAcc.IsValid)
    {
        MessageBox.Show("..");
        Close();
    }
    else
    {
        Popup.Close();      // Error caused by closing form from different thread
        MessageBox.Show("");
    }
}

public Login()             // 'Main' form constructor
{
    InitializeComponent();

    ActiveAcc = new Account();
    Popup = new LoginWaiter();
    LoginProcess = new Thread(Popup.Show);      //Popup is an ordinary Form
}

我一直在尝试使用LoginProcess.Abort()Popup.Dispose()等各种工具来使其正常工作,但即使app正在运行时环境中,由于引发了异常,它仍然不稳定。 如果有任何帮助,我将不胜感激,对于描述问题的含糊不清,我感到很遗憾。

1 个答案:

答案 0 :(得分:1)

为什么不让UI线程执行诸如打开和关闭表单之类的UI,并生成其他线程(或后台工作程序或异步任务)来执行其他操作?

IMO,让其他线程尝试与UI线程上的元素进行交互(例如,让后台线程直接设置标签的文本或其他一些)是要求心痛。

如果您只是按原样保留代码,那么这是一件非常简单的事情。在Popup中,添加一个默认为true的静态bool。同样在Popup中,添加一个计时器任务,每隔X毫秒检查一次该布尔值的状态。如果它发现该值已设置为false,则让Popup告诉自己在该计时器滴答内关闭。

我对这个设计并不陌生,但它可能看起来像:

 public partial class Popup : Form
    {
        public static bool StayVisible { get; set; }

        private System.Windows.Forms.Timer timer1;

        public Popup()
        {
            StayVisible = true;
            this.timer1.Interval = 1000;
            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (!StayVisible) this.Close();
        }

    }

然后,从另一个线程,当您想要关闭Popup时,请调用

Popup.StayVisible = false;

更好的是,你会触发一个Popup会收到的事件,以便它可以自行关闭。由于您打算使用多个线程,因此您必须处理raising events cross-thread