gpt4 book ai didi

c# - 启动前显示对话框时,WPF应用程序立即退出

转载 作者:IT王子 更新时间:2023-10-29 04:34:06 25 4
gpt4 key购买 nike

更新:我想,我需要了解的是在WPF中启动应用程序之前显示对话框的“正确”,“受支持”方式。

这是代码:

    public partial class App : Application
{
[STAThread]
public static void Main()
{
var app = new App();
app.InitializeComponent();

new DialogWindow().ShowDialog();

app.Run( new MainWindow() );
}
}
DialogWindow出现预期。
但是关闭它后,应用程序立即退出。 MainWindow根本不显示!

我已经进行了一些调试,并将问题追溯到此:
  • 创建对话框后,它将成为app的MainWindow,因为目前没有MainWindow。
  • 因此,关闭对话框会使应用程序将ShutdownCallback发布到调度程序队列上。
  • 但是,调度程序运行的时间不足以执行回调。
  • 因此,一旦随后调用app.Run,队列中的第一件事就是ShutdownCallback,这自然会导致应用程序立即关闭。

  • 在进行了此分析之后,有一个明显的解决方法:在 MainWindow之后立即创建 App,从而使其成为 app的MainWindow,这将防止 DialogWindow导致应用程序关闭。

    但是,这让我感到困扰。

    首先,这对我来说似乎是肮脏的骇客。我的意思是,没有明确的理由以这种顺序创建窗口,而我只是通过一些调试发现了这一点。这不是受支持的方式。

    其次,这显然是一个错误。我的意思是,如果不明确支持关闭后创建第二个窗口,则应该抛出一些 InvalidOperationException,对吧?

    第三,这不仅是一个错误,而且看起来很幼稚,就像多线程初学者一样。

    所有这些使我相信,也许我在这里没有掌握一些基本知识?也许我根本没有道理?也许所有这些都应该以不同的方式完成?

    以下是一些背景:
    该应用程序必须在启动时进行一些引导。检查一下,设置异常处理程序,记录日志-您知道,通常的事情。在此过程中,可能有必要向用户寻求帮助-这是对话框的目的。

    我绝对不想将所有内容放到在 MainWindow.IsVisibleChanged或类似的代码上执行的状态机中。我想使其保持非常简单,简短和直接的方式- bootstrap 代码应该采用的方式,以便可以轻松地发现bug。

    最佳答案

    默认情况下,WPF应用程序的ShutdownMode为OnLastWindowClose。在代码中,您将显示一个窗口,然后将其关闭。因此,最后一个窗口关闭,应用程序关闭。然后在关闭时,显示另一个窗口。由于应用程序正在关闭,该窗口将立即关闭。

    因此,一切都按照您的设计和编程进行。

    但是,您需要做一些不同的事情:首先显示为唯一窗口的窗口应该是“特殊窗口”,关闭后要继续执行,则显示“主窗口”,然后退出应用程序一次(或与该应用程序关联的所有窗口)关闭。

    最简单的方法:首先将关闭模式设置为OnExplicitShutdown,然后在显示主窗口后将其设置为OnLastWindowClose或OnMainWindowClose。在代码中:

    public static void Main()
    {
    var app = new App();
    app.InitializeComponent();

    app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
    new DialogWindow().ShowDialog();

    var mainWindow = new MainWindow();
    app.MainWindow = mainWindow;
    app.Run(mainWindow);
    // When the window has loaded, it should then set the app.ShutdownMode to what you actually want.
    }

    编辑:
    我不确定你到底在做什么。您提供的代码将无法编译,因为当正确使用WPF应用程序类(带有App.xaml构建 Action 作为ApplicationDefinition)时,已经定义了Main方法。如果只有从Application派生的类,则没有InitializeComponent()方法。使代码得以编译的唯一方法是将构建操作手动更改为Page。但是,在这种情况下,Application.Current == app。

    因此,发生以下情况:
  • 应用程序启动。由于到目前为止尚未创建WPF应用程序,因此Application.Current为null。这也意味着没有调度程序循环正在运行并且调度程序消息未得到处理(请注意,调度程序循环还处理Windows消息)。
  • 创建一个新的App对象。 由于Application.Current为null,因此将其自身设置为Application.Current。
  • Application.Current.MainWindow为空,Application.Current.Windows为空列表。
  • 由于ShutdownMode为OnLastWindowClose,因此当当前应用程序(即应用程序)的最后一个窗口关闭时,将开始关闭。
  • 对话框以模态显示。由于没有调度程序循环正在运行,因此ShowDialog()本身将运行“本地”调度程序循环。
  • 实际上这是两个部分:首先,创建窗口。它属于当前应用程序,因此将其自身添加到Application.Current.Windows。由于它是显示的第一个窗口,而Application.Current.MainWindow为null,因此它也将自己设置为主窗口。其次,窗口以模态显示。
  • 由于Application.Current.Windows现在为非空,一旦为空,将开始关机。
  • 用户关闭对话框窗口。作为关闭的一部分,窗口将从Application.Current.Windows中删除。另外,由于它是MainWindow,因此将其设置为null。 由于Application.Current.Windows现在为空,因此开始关闭。但是,由于没有调度程序循环正在运行,因此尚未执行任何操作(仅设置内部标志或类似标志)。
  • 如果您使用了app.Run(new DialogWindow()); app.Run(new MainWindow());,则在创建MainWindow时会出现异常,因为在这种情况下,dispatcher-loop运行正常。因此,它实际上可以自行关闭,因此在创建MainWindow时,由于调度程序循环已关闭,因此它将引发异常。
  • MainWindow已创建。如上所述,它将自身添加到Application.Current.Windows并将其自身设置为Application.Current.MainWindow。
  • 但是,已经达到了关闭应用程序的条件。但是,到目前为止,该应用程序没有机会做任何事情。
  • 现在调用Run()。调度程序循环再次开始,现在有机会关闭应用程序。因此,它关闭了应用程序并关闭了所有打开的窗口。

  • 同样,没有错误。

    因此,解决此问题的一种方法是更改​​为OnExplicitShutdown。然后在步骤4中,没有达到关闭原因。更好的方法(如更像是普通的WPF应用程序)将是具有适当的ApplicationDefinition。从App.xaml中删除StartupUri,而是处理Startup事件:
    private void OnStartup(object sender, StartupEventArgs e)
    {
    this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
    new DialogWindow().ShowDialog();

    var mainWindow = new MainWindow();
    this.ShutdownMode = ShutdownMode.OnLastWindowClose; // or OnMainWindowClose
    mainWindow.Show();
    }

    由于关闭对话框窗口时我们具有OnExplicitShudown,因此应用程序没有理由在此时开始关闭。然后,在创建MainWindow之后,我们又有了一个窗口作为主窗口和应用程序窗口(之一)。因此,我们可以切换到实际需要的关闭模式并显示主窗口。

    关于c# - 启动前显示对话框时,WPF应用程序立即退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3702785/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com