我见过很多像这样的问题,但我一直遇到异常现象。我正在尝试初始化一些表单,使用主表单调用Application.Run(...)
而不显示任何非主表单,执行一些操作,然后动态显示/隐藏其余表单。一些虚拟代码如下。
public static void Main() {
MainForm = new DebugUserInterface(); // just a dummy form
SubForm = new DebugUserInterface(); // ditto
Task.Run((Action) DoWork); // schedule some work on another thread
Application.Run(MainForm); // start the message pump
}
private static void DoWork() {
Thread.Sleep(1000); // pretend to do some work
SubForm.Invoke((Action) SubForm.Show); // show the other form
// should occur after the message pump has started
}
子表单永远不会出现。有趣的是,如果我在启动消息泵之前调用SubForm.Show()
,子表单只显示并且行为正确,但我希望某些表单保持不可见,未初始化,甚至还不存在(如果我想创建的话)在调用Application.Run(...)
之前,在运行时形成。
我正在使用Mono 5.0.0.100 for macOS来编译此代码并测试在macOS(使用Mono运行时和Wine)和Windows(使用.NET运行时)上运行代码。
答案 0 :(得分:1)
Hans's comment是准确的,但恕我直言会引导你走错路。确实,你不能使用SubForm
对象回到正确的线程,因为它的句柄还没有被创建。但是你有另一个 具有有效句柄的对象:MainForm
对象。
此外,您可以使用Form.Shown
事件确保您的代码在MainForm
显示之前不会执行(特别是具有有效句柄)。
最后,如果您利用新的async
/ await
范例,您可以完全避免显式调用。该框架将为您完成。
把它们放在一起,它可能看起来像这样:
public static void Main() {
MainForm = new DebugUserInterface(); // just a dummy form
SubForm = new DebugUserInterface(); // ditto
MainForm.Shown += async (sender, e) =>
{
await Task.Run(DoWork);
SubForm.Show();
};
Application.Run(MainForm); // start the message pump
}
private static void DoWork() {
Thread.Sleep(1000); // pretend to do some work
}
请注意,通过上述操作,使用事件处理程序的匿名方法,您甚至不需要MainForm
和SubForm
变量的静态字段。如果你愿意,你可以制作那些局部变量。