ser*_*hio 3 .net testing exception-handling throw winforms
我使用此代码来捕获WinForm应用程序UnhandledException.
[STAThread]
static void Main(string[] args)
{
// Add the event handler for handling UI thread exceptions to the event.
Application.ThreadException += new
System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
// Set the unhandled exception mode to force all Windows Forms errors
// to go through our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
try
{
Application.Run(new MainForm());
} catch....
Run Code Online (Sandbox Code Playgroud)
在那里,我将尝试重新启动应用程序.现在我的问题是模拟这样的异常.我尝试过之前尝试过(在主要方面):throw new NullReferenceException("test");
VS抓住了它.
在按钮的MainForm代码中也尝试过:
private void button1_Click(object sender, EventArgs ev)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(TestMe), null);
}
protected void TestMe(object state)
{
string s = state.ToString();
}
Run Code Online (Sandbox Code Playgroud)
没有帮助,VS即使在发布模式下也能抓住它.
UnhandleldException
?CurrentDomain_UnhandledException
吗?ThreadException
?PS.
如果我在VS外面启动一个windows通用窗口
应用程序MyApplication"遇到错误,应该关闭... blabla ...发送报告/不发送.
但是,我希望VS输入此方法(... Domain_Unhahdled ...)
编辑:当重新启动应用程序,是否有可能禁用Windows崩溃的消息出现,如: 替代文字http://byfiles.storage.msn.com/y1pOhWnAAXfMYtJH2VNa5iL0l1hjAqNHD2VmVnl8nN6L1oQC_xHkyHCJxhMc1ZLxLOH9ZXfZoo5zX8?PARTNER=WRITER ?
码:
static void CurrentDomain_UnhandledException(object sender,
UnhandledExceptionEventArgs e)
{
// Since we can't prevent the app from terminating
// log this to the event log.
Logger.LogMessage(ERROR, errorMsg);
Application.Restart();
Run Code Online (Sandbox Code Playgroud)
我仍然不完全确定我理解这个问题,但有几点需要注意:
Application.ThreadException
并且Application.SetUnhandledExceptionMode
仅适用于Windows窗体线程.ThreadPool
即使在Winforms应用程序中,任意线程实际上也不是Windows窗体线程,因此这两行代码无效.
注册事件AppDomain.CurrentDomain.UnhandledException
将捕获ThreadPool
线程上发生的异常.
但是,UnhandledException
事件实际上无法处理异常.到那时,停止进程终止是为时已晚,如果在后台线程上发生异常(除非您启用了旧的.NET 1.1行为,但是......不这样做),这将永远发生.)此事件是真的只适合记录或清理.
我自己使用类似于你的测试代码测试了这个,并验证了异常"handler"中的代码确实执行了.但该应用程序仍将崩溃,你无法阻止它.
更新:我将再尝试一次,就是这样.
如果您的目标是始终运行无人值守应用程序,那么您有三种选择:
妥善处理您的例外情况.到目前为止,这是最好的,也许是唯一正确的解决方案.挂钩AppDomain.UnhandledException
是没有处理异常.当控件进入该事件处理程序时,您的应用程序已经崩溃.你不能再保存了.
从后台线程中逃避的未处理异常是您需要修复的代码中的灾难性错误.从后台线程中逃避的未处理异常是您需要修复的代码中的灾难性错误.从后台线程中逃避的未处理异常是您需要修复的代码中的灾难性错误. 请不要再评论"我不在乎" - 你需要开始关怀.
礼貌地请求Windows 为您重启应用程序. 与尝试从崩溃处理程序重新启动不同,这是一个非常糟糕的想法,原因太多而无法完全枚举(数据损坏,无限重启循环,资源泄漏,操作系统不稳定等),注册重启实际上允许这种情况发生在半控制的时尚.正如我在评论中提到的,在.NET中与这个API互操作很简单.您在应用程序启动时立即注册,而不是在崩溃且您的应用程序处于不受信任状态时注册.
创建一个监视应用程序的超级用户服务,如果崩溃则重新启动它.对于之前两点中讨论的许多原因,这仍然是不好的,但你至少在一定程度的稳定性上有战斗机会.
通过使用命名的互斥锁,在主管中等待,并观察WAIT_ABANDONED
状态(AbandonedMutexException
在.NET中),您可以获得非常可靠的应用程序崩溃指示.抛弃状态仅在拥有互斥锁的进程终止而不释放它时发生 - 即具有未处理的异常.通过更多的互操作,您还可以检测并关闭崩溃窗口.
这些是你的选择.我强烈建议您处理后台线程上的异常,因为从后台线程中逃避的未处理异常是您需要修复的代码中的灾难性错误. 如果它来自外部组件并且您无法捕获它,那么灾难性错误就在该组件中,您应该考虑将其报告给作者或使用其他组件.
如果应用程序不够稳定,无法实际运行,那么简单地要求"此应用程序必须始终运行且应完全忽略致命崩溃"并不能使该方案成为可能.崩溃是一次崩溃.如果引擎突然死亡,您不会设计汽车立即重新启动.您可以做的最好的事情是询问受信任的运营商,无论是人工操作员,操作系统还是某些监控软件 - 代表它重新启动应用程序.
这个问题的变化似乎经常出现 - 基本上,"我的应用程序永远不应该崩溃,或者如果确实如此,它应该是隐形的.我想吃掉每一个未处理的异常,并假装它没有发生." 这不仅是不可能的,而且几乎与好的设计的每一个原则背道而驰(特别是"快速失败"原则,它当然可以重新解释,但绝不应完全忽略).
这就是我所能说的.如果你不愿意接受任何一个,那么祝你好运找到一个可行的选择.