如果在 WPF 4.0 中使用启动屏幕,带有异常详细信息的 MessageBox 会立即消失

发布于 2024-09-26 20:20:38 字数 924 浏览 1 评论 0原文

我的基于桌面的 WPF 应用程序 (4.0) 使用数据库,为此,它应该在应用程序启动时建立与 SQL Server 的连接。当然,此操作需要一些时间,用户必须在 .Net Framework 启动并连接到 SQL Server 时等待几秒钟(3-5 秒)。

在这种情况下,我决定使用启动画面。我在解决方案中添加了一些图片,将构建操作设置为“启动屏幕”,编译了我的应用程序,它有效!如果尝试连接到 SQL Server 失败(例如服务器不可用),我的应用程序会引发异常,并且我会向用户 MessageBox 显示警告和异常详细信息,用户按“确定”并关闭应用程序 (Application.Current.Shutdown())。

在我添加启动屏幕之前,所有这些逻辑都可以完美地工作,但是现在,添加启动屏幕后,如果我在 SQL Server 不可用时运行应用程序,应用程序会抛出异常(正如我在代码中询问的那样),但是 MessageBox带有通知的 会出现 1-2 秒,然后消失,无需任何用户交互,用户甚至无法阅读上面写的内容。

我发现,如果我尝试显示 2 个 MessagBoxes,那么第一个将立即出现并消失,但第二个将一直保留,直到用户按下“确定”。

如何解决这个问题?我想使用启动屏幕并在引发异常时显示一个 MessageBox 并让用户决定何时关闭它(用户单击“确定”按钮)。

这是描述我的应用程序逻辑的流程图:

也不例外(好的场景): 运行应用程序 → 启动屏幕 → if(isConnectedToSQL=true) → 显示主窗口...

但有例外(糟糕的场景): 运行应用程序 → 启动屏幕 → if(isConnectedToSQL=false) → 抛出异常 → 显示带有异常详细信息的消息框 → 用户单击“确定” → 关闭应用程序。

My desktop-based WPF-application (4.0) works with DB and in order to this it should establish a connection with SQL Server on application's startup. Of course, this operation takes some time and user have to wait some seconds (3-5) while .Net Framework start and connect to SQL Server.

As appropriate in such kind of cases I decided to use a splash screen. I added some picture to the solution, set build action as «Splash screen», compiled my application, it works! If the attempt to connect to SQL Server failed (e.g. server is not available) my application throws an exception and I show to user MessageBox with warning and exception details, user press OK and application shutdowns (Application.Current.Shutdown()).

Before I added splash screen all this logic used to work perfectly, but now, with splash screen added, if I run application while SQL Server is not available, application throws an exception (as I asked in my code), but MessageBox with notification appears for 1-2 seconds and disappear without any user interaction, user even can't read what is written on it.

I discovered, that if I try to show 2 MessagBoxes, so the first one will appear and disappear immediately, but the second one will stay until the user will press OK.

How to solve this issue? I want to use splash screen and show one MessageBox if an exception has been thrown and let the user to decide when to close it (user click on the OK button).

Here is a flow chart describes logic of my application:

No exception (good scenario):
Run app → Splash screen → if(isConnectedToSQL=true) → Show main window…

With exception (bad scenario):
Run app → Splash screen → if(isConnectedToSQL=false) → Throw exception → Show MessageBox with exception details → User click on OK → Close application.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浊酒尽余欢 2024-10-03 20:20:38

原因在于 SplashScreen 如何使用 BeginInvoke 来关闭自身。我无法确定 MessageBox 被关闭的确切位置*,但我确实看到了一个简单的修复:

不要使用 MessageBox。

创建一个错误窗口,我们将其命名为“ErrorWindow.xaml”。使用该窗口向用户显示错误消息并响应“确定”按钮。

按照此指南声明您自己的 Main 过程并按如下所示进行更改:

编辑以显示如何将信息传递到 ErrorWindow。

public static void Main()
{
    SplashScreen splashScreen = new SplashScreen("whatever.jpg");
    splashScreen.Show(true);
    string errorMessage;
    bool dataLoaded = LoadDataFromDatabase(out errorMessage);
    WpfApplication1.App app = new WpfApplication1.App();
    Window windowToRun = dataLoaded ? (Window)new MainWindow() : (Window)new ErrorWindow { ErrorMessage = errorMessage };
    app.Run(windowToRun);
}
  • 我的猜测是 SplashScreen.Show 和 Application.Run 是两个独立的消息泵。第一个通过调用 PostQuitMessage 来终止。这解释了 MessageBox 关闭的原因。

The reason lies in how the SplashScreen uses BeginInvoke to Close itself. I couldn't pin down exactly where the MessageBox is getting closed*, but I did see a simple fix:

Don't use MessageBox.

Create an error window, let's call it "ErrorWindow.xaml". Use that window to display the error message to the user and respond to the OK button.

Follow this guideline to declare your own Main procedure and alter it like so:

Edited to show how you might pass info to the ErrorWindow.

public static void Main()
{
    SplashScreen splashScreen = new SplashScreen("whatever.jpg");
    splashScreen.Show(true);
    string errorMessage;
    bool dataLoaded = LoadDataFromDatabase(out errorMessage);
    WpfApplication1.App app = new WpfApplication1.App();
    Window windowToRun = dataLoaded ? (Window)new MainWindow() : (Window)new ErrorWindow { ErrorMessage = errorMessage };
    app.Run(windowToRun);
}
  • My guess is that SplashScreen.Show and Application.Run are two separate message pumps. The first is terminated with a call to PostQuitMessage. That explains why the MessageBox closes.
哆兒滾 2024-10-03 20:20:38

在类似的 StackOverflow 问题上,我列出了处理此问题的几种不同方法。

如果@Tergiver 的方法不适用于您的应用程序,您可能会发现其中一些其他技巧很有用。

如何将 wpf MessageBox.Owner 设置为桌面窗口,因为 SplashScreen 会关闭 MessageBox

On a similar StackOverflow question, I listed several different approaches for dealing with this problem.

You might find some of these other tricks useful if @Tergiver's approach doesn't work for your application.

how to set wpf MessageBox.Owner to desktop window because SplashScreen closes MessageBox

暮年慕年 2024-10-03 20:20:38

鉴于问题描述位于
https://connect.microsoft.com/VisualStudio /feedback/details/381980/wpf-splashscreen-closes-messagebox#tabs 解决此问题的一种方法是在调用 MessageBox.Show 之前使用 DllImport SetActiveWindow 并将其调用为 SetActiveWindow(IntPtr.Zero)。那么消息框不会将启动屏幕作为其父级,并且当启动屏幕自行关闭时也不会消失。

Given the problem description at
https://connect.microsoft.com/VisualStudio/feedback/details/381980/wpf-splashscreen-closes-messagebox#tabs one way to solve this is to DllImport SetActiveWindow and call it as SetActiveWindow(IntPtr.Zero) just before calling MessageBox.Show. Then the message box won't get the splash screen as its parent and won't die when the splash screen closes itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文