哪些例外不应该抓住? [英] Which exceptions shouldn't I catch?

查看:189
本文介绍了哪些例外不应该抓住?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序运行一个长批处理进程,其中可能会抛出许多异常。如果在批处理中的一个项目中抛出非关键异常,我想简单地记录并继续,所以我们可以稍后解决问题,同时让其他批处理项目继续。



一些例外,例如 OutOfMemoryException ,对整个应用程序都是毁灭性的,我想重新抛出,以便它们冒泡到全局异常处理程序,它将记录错误并停止应用程序。



所以我的问题是,是否有一个简单的关键异常列表我可以在抑制(记录日志之后)其他所有东西时重新抛出我的较低的异常处理程序?



谢谢!



b>编辑:要详细说明一下,这里是我的程序的基本结构

  foreach(var item in longItemList)
{
try
{
bigDynamicDispatchMethod(item);
}
catch(Exception ex)
{
logException(ex);
}
}

有可能会抛出大量异常,因为这个循环几乎在我的应用程序的顶层。我项目中99%的代码落后于调度方法。我在较低级别进行合理的异常处理,但是错误仍然在进行中,我不想在抛出异常之后停止批处理中的其他无关进程。



尝试找到在我的应用程序中其他地方可能抛出的异常似乎是一项艰巨的任务,似乎是获得黑名单的关键异常会更简单。



有没有更好的方法来构造我的应用程序来处理这个问题?我很乐意提出建议。

解决方案

你不需要列出坏的例外,你应该把一切都看作是坏的默认。只抓住你可以处理和恢复的东西。 CLR 可以 通知您未处理的异常,以便您可以正确登录。吞噬一切除了黑色列出的例外不是修复您的错误的正确方式。这只会掩盖他们。请阅读这个


不要排除任何特殊的异常,以捕获目的
转移异常。



而不是在你的catch中创建特殊的异常列表条款,
你应该只捕获你可以合法地
句柄的那些异常。您不能处理的异常不应被视为非特定异常处理程序中的
特殊情况。
以下代码示例演示错误地测试特殊的
异常,以重新抛出它们。




  public class BadExceptionHandlingExample2 {
public void DoWork(){
//做一些可能抛出异常的工作。
}
public void MethodWithBadHandler(){
try {
DoWork();
} catch(Exception e){
if(e is StackOverflowException ||
e is OutOfMemoryException)
throw;
//处理异常,
//继续执行。
}
}
}

几个其他规则: p>


避免通过捕获非特定异常来处理错误,例如
System.Exception,System.SystemException等,在应用程序
代码。有些情况下处理应用程序中的错误是
可以接受,但这种情况很少见。



应用程序不应该处理可能导致的异常一个
意外或可利用的状态。如果您无法预测所有可能的
原因的异常,并确保恶意代码不能利用
生成的应用程序状态,则应该允许应用程序
终止而不是处理异常。



当您了解为什么
将在给定的上下文中抛出时,请考虑捕获特定的异常。



您应该只捕获可以从中恢复的那些异常。对于
示例,由尝试打开
a不存在的文件导致的FileNotFoundException可以由应用程序处理,因为它可以
将问题传达给用户,并允许用户指定
不同的文件名或者创建文件。打开
生成ExecutionEngineException的文件的请求不应该被处理,因为
导致异常的根本原因不能被确定为任何学位
,应用程序不能确保它是

  Exc。类型|做什么|示例
------------ | -------------------------------- ----- | -------------------
致命|没什么,让CLR处理它| OutOfMemoryException
------------ | -------------------------------- ----- | -------------------
Boneheaded |修复导致异常的错误ArgumentNullException
------------ | -------------------------------- ----- | -------------------
Vexing |修复导致异常的错误FormatException from
| (通过捕获异常,因为| Guid构造函数
|框架没有提供其他方式|(在.NET 4.0
|处理方式中修复)。通过Guid.TryParse打开MS Connect |
|问题。 |
------------ | --------------------------------- ---- | -------------------
外生|以编程方式处理异常| FileNotFoundException

大致相当于 Microsoft的分类:用法,程序错误和系统故障。
您还可以使用静态分析工具,例如 FxCop 来执行一些这些规则。


I have an app that runs a long batch process where many exceptions could potentially be thrown. If a non-critical exception is thrown during one item in the batch, I want to simply log it and continue, so we can fix the problem later while letting the other batch items continue.

Some exceptions, such as OutOfMemoryException, are devastating to the app as a whole, and these I would like to rethrow so that they bubble up to global exception handler which will log the error and stop the app.

So my question is, is there a reasonbly short list of critical exceptions that I can rethrow in my lower exception handler while suppressing (after logging) everything else?

Thanks!

Edit: To elaborate a little, here is the basic structure of my program

foreach(var item in longItemList)
{
   try
   {
      bigDynamicDispatchMethod(item);
   }
   catch(Exception ex)
   {
      logException(ex);
   }
}

There are potentially a huge number of exceptions that could be thrown because this loop is pretty much at the top level of my app. 99% of the code in my project is behind the dispatch method. I do reasonable exception handling at lower levels, but bugs still work their way in and I don't want to stop other unrelated processes in the batch after an exception is thrown.

Trying to find which exceptions could be thrown everywhere else in my app seems like a daunting task, and it seemed to be that it would be simpler to get a blacklist of critical exceptions.

Is there a better way to structure my app to deal with this? I am open to suggestions.

解决方案

You don't need a list of 'bad' exceptions, you should treat everything as bad by default. Only catch what you can handle and recover from. CLR can notify you of unhandled exceptions so that you can log them appropriately. Swallowing everything but a black listed exceptions is not a proper way to fix your bugs. That would just mask them. Read this and this.

Do not exclude any special exceptions when catching for the purpose of transferring exceptions.

Instead of creating lists of special exceptions in your catch clauses, you should catch only those exceptions that you can legitimately handle. Exceptions that you cannot handle should not be treated as special cases in non-specific exception handlers. The following code example demonstrates incorrectly testing for special exceptions for the purposes of re-throwing them.

public class BadExceptionHandlingExample2 {
    public void DoWork() {
        // Do some work that might throw exceptions.
    }
    public void MethodWithBadHandler() {
        try {
            DoWork();
        } catch (Exception e) {
            if (e is StackOverflowException ||
                e is OutOfMemoryException)
                throw;
            // Handle the exception and
            // continue executing.
        }
    }
}

Few other rules:

Avoid handling errors by catching non-specific exceptions, such as System.Exception, System.SystemException, and so on, in application code. There are cases when handling errors in applications is acceptable, but such cases are rare.

An application should not handle exceptions that can result in an unexpected or exploitable state. If you cannot predict all possible causes of an exception and ensure that malicious code cannot exploit the resulting application state, you should allow the application to terminate instead of handling the exception.

Consider catching specific exceptions when you understand why it will be thrown in a given context.

You should catch only those exceptions that you can recover from. For example, a FileNotFoundException that results from an attempt to open a non-existent file can be handled by an application because it can communicate the problem to the user and allow the user to specify a different file name or create the file. A request to open a file that generates an ExecutionEngineException should not be handled because the underlying cause of the exception cannot be known with any degree of certainty, and the application cannot ensure that it is safe to continue executing.

Eric Lippert classifies all exceptions into 4 groups: Fatal, 'Boneheaded', Vexing, Exogenous. Following is my interpretation of Eric's advice:

  Exc. type | What to do                          | Example
------------|-------------------------------------|-------------------
Fatal       | nothing, let CLR handle it          | OutOfMemoryException
------------|-------------------------------------|-------------------
Boneheaded  | fix the bug that caused exception   | ArgumentNullException
------------|-------------------------------------|-------------------
Vexing      | fix the bug that caused exception   | FormatException from 
            | (by catching exception  because     | Guid constructor
            | the framework provides no other way | (fixed in .NET 4.0 
            | way of handling). Open MS Connect   | by Guid.TryParse)
            | issue.                              | 
------------|-------------------------------------|-------------------
Exogenous   | handle exception programmatically   | FileNotFoundException 

This is roughly equivalent to Microsoft's categorization: Usage, Program error and System failure. You can also use static analysis tools like FxCop to enforce some of these rules.

这篇关于哪些例外不应该抓住?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆