我的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正在运行时环境中,由于引发了异常,它仍然不稳定。
如果有任何帮助,我将不胜感激,对于描述问题的含糊不清,我感到很遗憾。
答案 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。