我不应该抓住哪些例外情况?

时间:2011-08-22 19:13:05

标签: c# .net exception-handling

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

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

所以我的问题是,是否有一个合理的简短列表,我可以在我的下级异常处理程序中重新抛出,同时抑制(记录后)其他所有内容?

谢谢!

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

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

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

试图找到可以在我的应用程序中的其他地方抛出哪些异常似乎是一项艰巨的任务,而且似乎更容易获得关键异常的黑名单。

有没有更好的方法来构建我的应用程序来处理这个?我愿意接受建议。

6 个答案:

答案 0 :(得分:25)

您不需要“错误”例外列表,默认情况下您应该将所有内容视为错误。只抓住你可以处理和恢复的东西。 CLR can notify您处理未处理的异常,以便您可以正确记录它们。除了黑名单的异常之外,吞下一切都不是修复bug的正确方法。这只会掩盖他们。阅读thisthis

  

在捕获目的时不要排除任何特殊例外   转移例外。

     

而不是在catch子句中创建特殊异常列表,   你应该只抓住那些合法的例外   处理。您不能处理的例外情况不应视为   非特定异常处理程序中的特殊情况。该   下面的代码示例演示了错误的特殊测试   为了重新投掷它们的例外。

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.
        }
    }
}

其他几条规则:

  

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

     

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

     

当您了解具体异常时,请考虑捕获特定异常   将被抛弃在特定的背景下。

     

您应该只捕获可以从中恢复的异常。对于   例如,尝试打开导致的FileNotFoundException   应用程序可以处理不存在的文件,因为它可以   将问题传达给用户并允许用户指定   不同的文件名或创建文件。打开文件的请求   不应该处理生成ExecutionEngineException,因为   在任何程度上都无法知道异常的根本原因   确定性,应用程序无法确保它是安全的   继续执行。

Eric Lippert将所有异常分为4组:致命,'斩首',虚构,外生。以下是我对Eric的建议的解释:

  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 

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

答案 1 :(得分:11)

不要抓住任何你不知道如何安全处理的例外情况。

捕获Exception是一种特别糟糕的做法,唯一更糟的是catch,它没有指定任何托管异常类型(因为它也会捕获非托管异常)。

答案 2 :(得分:1)

问题可以支持更合适的设计:Which exceptions 应该我抓住了吗?

如果你确实需要捕获任何和所有异常并仍然继续,那么你应该使用AppDomain和单独的工作进程。或者将主机更改为ASP.NET或任务调度程序,它们已经完成了围绕进程隔离和重试的所有艰苦工作。

答案 3 :(得分:1)

除非您将HandleProcessCorruptedStateExceptions属性应用于异常处理函数,否则所有'不应由用户代码处理'的例外情况已被忽略,因此您可以处理除安全处理异常处理之外的任何事情。

答案 4 :(得分:1)

我会参考以下文章中的建议。

  

.NET Framework设计指南规则:不要捕获那些异常   你无法处理

http://www.codeproject.com/KB/cs/csmverrorhandling.aspx

同样来自参考文章:

  

你永远不应该在a中捕获System.Exception或System.SystemException   抓住障碍

答案 5 :(得分:1)

捕获您希望代码抛出的错误..当您使用API​​或方法时,请查看它将抛出的异常并仅捕获那些..您不应该列出异常列表并始终捕获这些异常。

  • 阅读msdn google异常处理最佳做法
  • 永远不会发现像Exception
  • 这样的非特定异常