【问题标题】:Application.Startup event limitations (bug?)Application.Startup 事件限制(错误?)
【发布时间】:2014-03-17 16:38:43
【问题描述】:

它说,我可以将Startup 事件用于很多事情,比如初始化、创建多个表单、blablabla。

但是,尝试创建一个新的 WPF 应用程序并添加此事件处理程序:

    private void App_Startup(object sender, StartupEventArgs e)
    {
        Window window = new Window();
    }

关闭主窗口后,您的应用程序将在内存中挂起。在那一刻暂停在 VS 中执行将丢弃丑陋的 crash 调用堆栈窗口,其中有很多调用远离我的源代码。

有什么想法吗?

P.S.:我需要为自学配置目的实例化我的所有窗口一次。我应该使用其他地方吗?


让我举一个更好的例子(上面的例子很好地重现了这个问题,似乎很难理解我实际上在做什么)。我删除 StartupUri 然后:

    private void App_Startup(object sender, StartupEventArgs e)
    {
        // un-comment this line to reproduce the problem:
        // Window window = new Window();

        // actual implementation will be
        // Window1 window1 = new Window1();
        // Window2 window2 = new Window2();
        // Window3 window3 = new Window3();
        // Window4 window4 = new Window4();
        // ...

        // start main window as usually
        MainWindow mainWindow = new MainWindow();
        mainWindow.Show();
    }

为什么我需要窗口实例(window1、..2、..3、...)?因为将检查它们的内容以创建我要为其保存配置的控件列表。其中一些窗口将从不显示给用户(例如,如果他不是管理员),其中一些是弹出窗口,一些是编辑器等。所以我不想显示它们。但是在任何应用程序启动时,都必须创建并保存配置。我现在正在寻找这样做的地方。

令人惊讶的是,使用专用事件 Startup 在创建多个窗口时似乎存在一些问题,但不显示它们。问题是为什么以及如何解决它。


测试更多。试试这段代码并解释一下,为什么关闭应用程序而不显示 any 窗口?

    private void App_Startup(object sender, StartupEventArgs e)
    {
        Window window = new Window();
        window.Close(); // closing without opening window

        MainWindow mainWindow = new MainWindow();
        mainWindow.Show();
        //mainWindow = new MainWindow(); // can be un-commented, for absolutely no effect
        mainWindow.Show();
        mainWindow.Show();
        mainWindow.Show();
        mainWindow.Show(); // you will not see mainWindow at all, all Show doing nothing
    }

更多问题。我该怎么办?


有用但有味道的东西:

    private void App_Startup(object sender, StartupEventArgs e)
    {
        Window window = new Window();

        MainWindow mainWindow = new MainWindow();
        mainWindow.ShowDialog();
        Shutdown();
    }

注意,调用ShowDialog(这将使事件处理程序等待该窗口关闭)并在之后调用Shutdown

目前尚不清楚Startup 事件处理程序在创建某些窗口的实例时有什么问题。有什么想法吗?

【问题讨论】:

  • 你遇到了什么崩溃?
  • @RohitVats,添加了屏幕截图。你能尝试重现这个问题吗?
  • 这不是崩溃窗口,只是堆栈跟踪。在窗口上调用 Show() 以便用户可以关闭它并让应用退出。
  • @HansPassant,不显示窗口如何解决?
  • 我不知道你为什么要这样做。我猜只是再次调用 Close()。

标签: c# wpf window


【解决方案1】:

通过这样做,您刚刚创建的窗口已成为主窗口:StartupUri 中指定的窗口将仅在启动事件之后立即创建。默认情况下,必须关闭主窗口才能关闭应用程序。由于它从未显示,用户没有机会这样做,应用程序似乎永远挂起。当执行暂停时,您看到的是一个正常的消息循环,这里没有崩溃。添加window.Show() 以查看您真正的“主”窗口。

如果您决定手动实例化主窗口,请从您的App.xaml 中删除StartupUri 属性。或者,在主窗口的Loaded 事件被触发后,保留该属性并实例化其他窗口。

【讨论】:

  • 好的,我删除了StartupUri 并在Startup 事件之后 启动主窗口该行(创建Window 实例)。关闭 main 窗口时应用程序仍然停止。
  • 关于Loaded事件,你知道我在哪里可以看到事件的顺序吗?因为如果我没看错的话,Loaded 就是渲染元素的时候,对我来说这听起来像是shown first timer 事件。但是,正如我所说,我根本不愿意展示那种形式。有趣的是,有投票者会费心重现这个问题吗?
  • 我不明白你所说的“之后”是什么意思。您应该删除 .xaml 文件中的 StartupUri。添加 Show() 调用以进行测试以查看创建的窗口。你会注意到一个仍然打开。是的,Loaded 是在渲染元素时,请改用第一个解决方案(在 App.xaml 文件中没有 StartupUri 的启动事件)。
  • 查看问题编辑。是的,我在 .xaml 文件中删除了 StartupUri。是的,如果我为每个实例化窗口添加Show,它将工作。现在,如何让应用程序运行不显示窗口(我多次提到过)?关于Loaded,它究竟是什么时候触发的?它会在我实例化时触发还是在显示之前触发?但是显示意味着显示窗口,如果你没看错的话,这不是我想要的。问题仍然悬而未决:为什么在Startup 事件中实例化窗口(不显示它)是一个问题以及如何解决它?
  • 这不是问题,这是默认行为!如果您不想等待主窗口关闭应用程序关闭(因为您选择隐藏该窗口),请在您认为合适时手动拨打Application.Shutdown时间。例如,当特定窗口已关闭时。实际上,Loaded 在显示之前触发,因此不适用于您的情况。
【解决方案2】:

我有解决方案,这对我来说似乎很好。想法类似于winforms - 在Main 中做所有事情。

然而,这在 wpf 中有点棘手(我使用this 问题作为指导):

  • App.xaml 中删除StartupUri
  • App.xaml 属性Build Action 设置为Page(这听起来很奇怪,但它适用于桌面应用程序)。这将从自动生成的类(App.g.csApp.g.i.cs)中删除 Main 方法。
  • 手动将Main方法添加到Application中:

.

public partial class App : Application
{

    [STAThread]
    public static void Main()
    {
        Window window1 = new Window();
        Window window2 = new Window();
        Window window3 = new Window();
        // ...

        MainWindow start = new MainWindow();
        start.ShowDialog();

        SomeOtherWindow next = new MainWindow();
        next.ShowDialog();

    }
}

现在我可以直接控制显示哪个窗口以及何时显示(程序流控制),并且在创建窗口实例而不显示它们时,不再有 bug 不关闭应用程序。

可疑之处在于这个Page 设置和那个事实,我没有实例化Application,也没有调用Run()。不知道以后会不会有问题。很高兴知道这一点。


可能仍然需要初始化应用程序(加载资源?),然后

    [STAThread]
    public static void Main()
    {
        App app = new App();
        app.InitializeComponents();

        // ... the rest
        // possibly app.MainWindow = start; or app.MainWindow = next;
        // if only 1 window, then app.Run(new MainWindow());
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 2018-11-12
    • 2014-10-14
    • 2015-10-30
    • 1970-01-01
    • 2014-05-27
    • 2011-08-25
    相关资源
    最近更新 更多