6

我正在玩一些 C# Winforms/WPF 代码,只是偶然发现了一些奇怪的东西。假设我有这样的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DoSomething();

        // maybe something more if everything went ok
    }
}

令我困惑的是,在构造函数完成其工作之前,我不能简单地从方法 DoSomething 关闭应用程序。如果在执行过程中有任何DoSomething失败,我需要立即关闭应用程序,但它只是继续运行,执行部分// maybe something more...然后关闭,但这对我来说太晚了。

我必须将用于关闭表单的代码放在构造函数本身中return;,然后它才能工作,但我并没有真正找到一个可以接受的解决方案。我正在尝试将此类验证逻辑从构造函数移至我的方法。

我尝试过类似的事情

public void DoSomething()
{
    Close();
}

或者

public void DoSomething()
{
    Application.Current.Shutdown();
}

但这似乎不起作用。是的,这两个代码都关闭了应用程序,但只有在完全完成的构造函数代码之后。

Why我需要这样的东西吗?好吧,因为在启动时我需要检查各种事情,比如连接和硬件的可用性,验证用户等,如果有任何失败,执行更多代码也没有意义。

使用 Winforms 和 WPF(因此有标签)尝试了相同的原理,效果相同。

任何人都可以提供解释或解决方案吗?

4

7 回答 7

8

只需尝试Environment.Exit(-1)在您的情况下使用,一切都会好起来的。

补充: 这是我能为你得到的最好的参考。

vs vs之间的区别Application.ExitApplication.ShutdownEnvironment.Exit

Application.Exit()用于以优雅的方式退出 Windows 窗体应用程序。基本上,它会在调用 Application.Run() 之后停止消息泵,关闭所有窗口并让您回到 Main() 方法。但是,有时它似乎不起作用 - 这通常是因为还有其他前台线程(除了 UI 线程)仍在运行,它们正在阻止线程结束。

Application.Shutdown()(大致)相当于 WPF 应用程序中的 Application.Exit() 。但是,您有更多的控制权,因为您可以设置 ShutDownMode 以便应用程序在主窗口关闭、最后一个窗口关闭或仅在调用此方法时关闭。

Environment.Exit()杀死所有正在运行的线程,进程本身就死了。这应该仅在更优雅的方法由于某种原因无法正常工作时作为最后的手段在 WF 或 WPF 中使用。它还可用于从控制台应用程序中突然退出。

另一个参考:如何正确退出 C# 应用程序?

于 2012-11-10T09:27:01.753 回答
3

你总是可以忽略你的开发人员,只使用Environment.FailFast()

但真的 - 不要。如果您有关键的事情要做,SA 验证串口是否连接到核电站,请提前做。没有规则强迫你一接到Application.Run(...)电话Main()就去。

于 2012-11-10T09:25:00.723 回答
1

已经为您的问题发布了可行的解决方案。

只是为了回答您的后续问题:诸如 Close() 和 Shutdown() 之类的方法不会立即退出您的应用程序的原因是它们都只是将消息推送到应用程序的消息队列中。它们仅在 MainWindow 的构造函数完成并且代码执行返回到消息处理循环后才被处理,甚至可能在队列中的其他一些仍待处理的消息也已处理之后。相反,诸如 Environment.Exit() 或 Environment.FailFast() 之类的方法是一种硬核操作系统功能,或多或少会导致立即终止进程。

于 2012-11-10T12:38:13.690 回答
0

一种解决方法是抛出异常并在application.UnhandledException

于 2012-11-10T09:21:11.180 回答
0

定义一个异常类:

public class InitializationException : Exception
{
    public InitializationException()
    {}

    public InitializationException(string msg)
        : base(msg)
    {}

    public InitializationException(string msg, Exception inner)
        : base(msg, inner)
    {}
}

并像这样更改您的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        try
        {
            DoSomething();

            // maybe something more if everything went ok
        }
        catch( InitializationException ex )
        {
            // log the exception
            Close();
        }
    }

    public void DoSomething()
    {
        if (notSomethingOK)
            throw new InitializationException( "Something is not OK and the applicaiton must shutdown." );
    }
}

这是一个干净且可维护的解决方案。

于 2012-11-10T09:29:09.737 回答
0
System.Windows.Forms.Application.Exit();
于 2016-01-29T08:03:12.140 回答
0

从概念上讲,此类东西不应在类构造函数中使用。构造函数在某种程度上是用起始状态初始化的,而不是可能发生的实际事情(如异常、消息框等)。

不要忘记您可以返回;来自构造函数,如果您需要中断其执行。这是更好的策略(大多数时候您不需要在错误时关闭应用程序而不显示一些文本)。

在 Windows/WPF 上的 C# 中有“显示窗口”、“可见性改变”、“加载”和许多其他事件,您可以虚拟覆盖或添加为事件处理程序。在那里初始化您的表单/应用程序。

它们是正常的方法,所以一切都按预期工作。您可以尝试抛出您的应用程序入口点(主函数)将捕获并忽略的异常。

对于 WPF,请检查: - https://msdn.microsoft.com/en-us/library/system.windows.forms.application.setunhandledexceptionmode(v=vs.110).aspx

于 2016-01-29T08:17:08.997 回答