Application.Run()后显示表单

时间:2017-05-25 21:52:06

标签: c# winforms

我见过很多像这样的问题,但我一直遇到异常现象。我正在尝试初始化一些表单,使用主表单调用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运行时)上运行代码。

1 个答案:

答案 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
}

请注意,通过上述操作,使用事件处理程序的匿名方法,您甚至不需要MainFormSubForm变量的静态字段。如果你愿意,你可以制作那些局部变量。