我使用此代码来捕获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....
在那里,我将尝试重新启动应用程序。现在我的问题是模拟这样的异常。我在尝试之前尝试过(主要):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();
}
没有帮助,VS即使在发布模式下也能抓住它。
UnhandleldException
?CurrentDomain_UnhandledException
?PS。
如果我在VS Windows通用窗口
之外启动应用程序MyApplication“遇到了 错误,应该是 关闭... blabla ...发送报告/不要 发送。
但是,我希望VS输入此方法(... Domain_Unhahdled ...)
编辑: 重新启动应用程序时,是否可以禁用Windows崩溃消息,如下所示: alt text http://byfiles.storage.msn.com/y1pOhWnAAXfMYtJH2VNa5iL0l1hjAqNHD2VmVnl8nN6L1oQC_xHkyHCJxhMc1ZLxLOH9ZXfZoo5zX8?PARTNER=WRITER ?
代码:
ThreadException
答案 0 :(得分:6)
我仍然不完全确定我理解这个问题,但有几点要提及:
Application.ThreadException
和Application.SetUnhandledExceptionMode
仅适用于Windows窗体主题。任意ThreadPool
线程实际上不是Windows窗体线程,即使在Winforms应用程序中也是如此,因此这两行代码无效。
使用AppDomain.CurrentDomain.UnhandledException
注册活动将捕获ThreadPool
个帖子上发生的异常。
但是,UnhandledException
事件实际上无法处理异常。到那时,停止进程终止是为时已晚,如果在后台线程上发生异常(除非您启用了旧的.NET 1.1行为,但是......不这样做),这将永远发生。)此事件是真的只适合记录或清理。
我自己使用与您类似的测试代码对此进行了测试,并验证了异常“handler”中的代码是否执行了。但是应用程序仍会崩溃,你无法阻止它。
更新:我打算再做一次尝试,就是这样。
如果您的目标是始终在无人值守的应用程序上运行,那么您有三个选择:
正确处理您的例外。这是到目前为止,是最好的,可能只是正确的解决方案。挂钩AppDomain.UnhandledException
不处理异常。当控件进入该事件处理程序时,您的应用程序已经崩溃。你不能再保存它了。
从后台线程转义的未处理异常是您需要修复的代码中的灾难性错误。从后台线程中逃避的未处理异常是您需要修复的代码中的灾难性错误。从后台线程中逃避的未处理异常是您需要修复的代码中的灾难性错误。请不要再对“我不关心”的效果发表评论 - 您需要启动< / em>关怀。
请求Windows 礼貌为您重新启动应用程序。与尝试从崩溃处理程序重新启动不同,这是一个非常糟糕的主意,原因太多了完全枚举(数据损坏,无限重启循环,资源泄漏,操作系统不稳定等),registering for a restart实际上允许这种情况以半控制的方式发生。正如我在评论中提到的,在.NET中interop with this API是直截了当的。您在应用程序启动时立即注册,而不是在崩溃且您的应用程序处于不受信任状态时注册。
创建一个监控应用程序的超级用户服务,如果崩溃则重新启动它。对于之前两点讨论的许多原因,这仍然是不好的,但你至少在一定程度的稳定性上有战斗机会。
通过使用命名的互斥锁,在主管中等待,并观察WAIT_ABANDONED
状态(.NET中的AbandonedMutexException
),您可以获得非常可靠的应用程序崩溃指示。抛弃状态仅在拥有互斥锁的进程终止而不释放它时发生 - 即具有未处理的异常。通过更多的互操作,您还可以检测并关闭崩溃窗口。
这些是您的选择。我强烈建议您处理后台线程上的异常,因为从后台线程中逃避的未处理异常是您需要修复的代码中的灾难性错误。如果它来自外部组件而您可以要抓住它,那么灾难性的bug就在那个组件中,你应该考虑将它报告给作者或使用不同的组件。
如果应用程序不够稳定,无法实际运行,那么简单地要求“此应用程序必须始终运行且应完全忽略致命崩溃”并不能使该方案成为可能。崩溃是一次崩溃。如果引擎突然死亡,您不会设计汽车立即重新启动。您可以做的最好的事情是询问受信任的运营商,无论是人工操作员,操作系统还是某些监控软件 - 代表它重新启动应用程序。
这个问题的变化似乎经常出现 - 基本上,“我的应用程序永远不应该崩溃,或者如果确实如此,它应该是隐形的。我想吃掉每一个未处理的异常并假装它没有发生。”这不仅是不可能的,而且与几乎所有良好设计原则背道而驰(特别是“快速失败”原则,当然可以重新解释,但绝不应完全忽略)。
这就是我所能说的。如果你不愿意接受任何一个,那么祝你好运找到一个可行的选择。
答案 1 :(得分:0)
Visual Studio可能会设置为中断异常,但如果您继续单步执行代码,它仍应遵循您所需的路径。您还应该尝试在VS之外运行该应用程序。
在未处理的异常之后重新启动应用程序是一个坏主意,因为您(根据定义)处于未知状态。如果异常条件永远不会改变,重新启动(如果可能的话)可能会使您处于永不停止的重启循环中。相反,请考虑尝试将异常信息记录到Web服务器,以便您可以调查并修复崩溃。在上传崩溃数据之前,请务必获得用户的许可。