我正在玩一些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(因此标签)尝试相同的原理,工作方式相同。
任何人都可以提供解释或解决方案吗?
答案 0 :(得分:8)
在你的情况下尝试使用Environment.Exit(-1)
,一切都会好的。
已添加: 这是我能为您提供的最佳参考资料。
Application.Exit
vs Application.Shutdown
vs Environment.Exit
Application.Exit()
用于以优雅的方式退出Windows窗体应用程序。基本上,它会停止消息泵,关闭所有窗口,并在调用Application.Run()之后立即返回Main()方法。但是,有时它似乎不起作用 - 这通常是因为还有其他前台线程(除了UI线程)仍在运行,这阻止了线程结束。
Application.Shutdown()
(广泛地)相当于WPF应用程序中的Application.Exit()。但是,您可以设置ShutDownMode,以便在主窗口关闭,最后一个窗口关闭或仅在调用此方法时关闭应用程序。
Environment.Exit()
会杀死所有正在运行的线程,而且这个过程本身就会死机。当更优雅的方法由于某种原因不起作用时,这应仅在WF或WPF中作为最后的手段使用。它还可以用于从控制台应用程序中突然退出。
答案 1 :(得分:3)
您可以随时忽略其他开发者,只需使用Environment.FailFast()
即可但是真的 - 不要。如果您有重要的事情要做,S.A验证串口是否与核电站相连,请事先做好。一旦Application.Run(...)
被调用,就没有规则强迫您Main()
。
答案 2 :(得分:1)
已经为您的问题找到了可行的解决方案。
回答你的后续问题:Close()和Shutdown()之类的方法没有立即退出应用程序的原因是两者都只是将消息推送到应用程序的消息队列中。它们仅在MainWindow的构造函数完成后处理,并且代码执行返回到消息处理循环,甚至在处理了队列中的其他一些待处理消息之后也是如此。 相反,像Environment.Exit()或Environment.FailFast()这样的方法是一种硬核os函数,导致或多或少立即杀死进程。
答案 3 :(得分:0)
解决方法是抛出异常并在application.UnhandledException
答案 4 :(得分:0)
定义一个Exception类:
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." );
}
}
这是一个干净且可维护的解决方案。
答案 5 :(得分:0)
System.Windows.Forms.Application.Exit();
答案 6 :(得分:0)
从概念上讲,这些事情不应该在类构造函数中使用。构造函数在某种程度上是用于初始化状态而不是实际的事情(例如异常,消息框等)。
如果您需要中断执行,请不要忘记您可以从构造函数返回; 。这是更好的策略(大多数情况下,您不需要在不显示某些文本的情况下关闭错误的应用程序)。
在Windows / WPF上的C#中有“显示窗口”,“可见性已更改”,“已加载”以及许多其他事件,您可以虚拟覆盖或添加为事件处理程序。在那里初始化您的表单/应用程序。
它们是正常的方法,所以一切都按预期工作。您可以尝试抛出应用程序入口点(主要功能)将捕获和忽略的异常。
对于WPF,请检查以下内容: - https://msdn.microsoft.com/en-us/library/system.windows.forms.application.setunhandledexceptionmode(v=vs.110).aspx。