【发布时间】:2016-09-22 08:05:57
【问题描述】:
我正在创建一个应用程序,它启动一个 FormSelect(),要求用户在列表中选择一个项目,当用户按下“选择”按钮时,它将创建一个 MainForm() 的新实例,隐藏 FormSelect 和显示 MainForm,但它不起作用,我所做的所有测试都出现异常。
这里有一些代码:
static class Program {
public static MainForm mainForm;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormSelect());
}
}
我的 FormSelect 没有什么特别之处,所以这里是单击它启动 MainForm 的按钮:
private async void btnSelect_Click(object sender, EventArgs e) {
loadingSpiner.Visible = true;
btnSelect.Enabled = false;
int index = listProcess.SelectedIndex;
await startMainForm(index);
this.Hide();
Program.mainForm.Show();
}
private async Task startMainForm(int index) {
await Task.Run(() => {
Program.mainForm = new MainForm(runningProcess[index]);
});
}
正如您在上面看到的,我正在使用一个任务来启动 MainForm,因此它不会冻结我的 UI 和我的“加载微调器”
但是当它尝试使用 .Show() 时,我得到了一个跨线程异常,所以我尝试使用以下方法调用该操作:
this.Invoke(new MethodInvoker(delegate () { Program.mainForm.Show(); }));
但是使用上面的方法我得到一个异常说:
System.Windows.Forms.dll 中出现“System.ComponentModel.Win32Exception”类型的异常,但未在用户代码中处理
附加信息:创建窗口句柄时出错。
如果我在 startMainForm 方法中删除“await Task.Run()...”,一切正常,但它完全阻止了 FormSelect UI。
如何避免这个问题?谢谢!
【问题讨论】:
-
你不应该从 uithread 打开任何 ui。
-
除了用于调用
Application.Run的线程(通常称为 UI 线程)之外,您不能在任何线程上创建 UI。 -
我认为运行应用程序时启动的“默认表单”是在 Program.cs 中指定的。在 Program.cs 中,您应该能够找到启动该表单的调用,它应该是阻塞的(因为那时我们是单线程的),然后添加代码以启动下一个表单?