我不应该捕捉哪些异常

本文关键字:异常 不应该 | 更新日期: 2023-09-27 18:06:17

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

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

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

谢谢!

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

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

可能会抛出大量异常,因为这个循环几乎是在我的应用程序的顶层。我的项目中99%的代码都在dispatch方法后面。我在较低的级别上做了合理的异常处理,但bug仍然会出现,我不想在抛出异常后停止批处理中其他不相关的进程。

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

是否有更好的方法来构建我的应用程序来处理这个?我愿意听取建议。

我不应该捕捉哪些异常

你不需要一个'bad'异常列表,你应该在默认情况下将所有异常视为bad。只抓你能处理的,并从中恢复。CLR可以通知您未处理的异常,以便您可以适当地记录它们。除了黑名单上的异常之外,吞下所有的东西并不是修复bug的正确方法。那只会掩盖它们。读这个和这个

在为目的捕获时不要排除任何特殊异常

不要在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.
        }
    }
}

其他规则:

通过捕获非特定异常来避免处理错误,例如系统。异常,系统。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 

这大致相当于微软的分类:使用、程序错误和系统故障。您还可以使用静态分析工具(如FxCop)来强制执行其中的一些规则。

不要捕捉任何你不知道如何安全处理的异常。

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

一个更合适的设计应该由以下问题支持:我应该捕捉哪些异常 ?

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

除非您将HandleProcessCorruptedStateExceptions属性应用于异常处理函数,否则所有"不应由用户代码处理"的异常都已经被忽略,因此您可以安全地处理除进程破坏性异常之外的任何其他异常。

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

。. NET框架设计准则规则:不要捕捉异常你不能处理

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

同样来自参考文章:

你永远不应该抓住System。异常或系统。系统异常catch块

捕获您期望代码抛出的错误。当你使用一个API或一个方法时,看看它会抛出什么异常,然后只捕捉那些异常。你不应该列出一个异常列表,然后总是抓住它们。

  • 从msdn中读取google异常处理最佳实践
  • 永远不要捕获非特定异常,如Exception