简体   繁体   English

尝试/捕获与AppDomain.UnhandledException来记录和崩溃应用程序

[英]try/catch vs AppDomain.UnhandledException to log & crash the application

As far as I know, you are supposed to only use try/catch when you will actually handle the exception and not just report&log it and then crash the application. 据我所知,您应该仅在实际处理异常时才使用try / catch,而不仅仅是报告和记录异常,然后使应用程序崩溃。 Otherwise, you are better off just checking different scenarios where it makes sense (eg if sth==null) or - if your purpose is just to log the exception and crash the application - to use AppDomain.UnhandledException . 否则,最好只检查有意义的其他方案(例如,如果sth == null),或者-如果您的目的只是记录异常并使应用程序崩溃,则最好使用AppDomain.UnhandledException But is this always the case and why? 但是,情况总是如此吗?为什么?

Suppose the following method, which accepts an array and returns MemoryStream after doing some database and filesystem operations. 假设以下方法接受一个数组,并在执行一些数据库和文件系统操作后返回MemoryStream。

MemoryStream Read (int[] IDs)
{
    try
    {
        using (SqlConnection connection = new SqlConnection(connection_string))
        {
            connection.Open();    

                        // a bunch of code executing SQL queries & constructing MemoryStream, which is returned at the end of the block
        }
    }
    catch (Exception e)
    {
        // report the exception to the user & log it
        throw; // pointles??                
    }
}

There are multiple situations that can be considered exceptional/unwanted behavior, such as: 有多种情况可以视为异常/不必要的行为,例如:

  • argument (IDs[]) being null, 参数(IDs [])为null,
  • failure to establish an SQL connection, 无法建立SQL连接,
  • failure to execute a specific SQL query. 无法执行特定的SQL查询。

All these cases are considered exceptional, still putting everything inside a try/catch if you only want to log an exception (then crash) is probably bad practice - but why? 所有这些情况都被认为是例外情况,如果您只想记录一个异常(然后崩溃),那么仍然将所有内容放入try / catch中可能是不好的做法-但是为什么呢? What would be the best handling behavior in the above case? 在上述情况下最佳的处理行为是什么? Avoid try/catch completely, check null references using an if statement (return null in such case) and use AppDomain.UnhandledException to log everything else? 避免完全尝试/捕获,使用if语句检查空引用(在这种情况下返回null),并使用AppDomain.UnhandledException记录其他所有内容? Use try/catch, but still check for null references inside using if statements (and return in that case)? 使用try / catch,但仍使用if语句检查内部是否为空引用(在这种情况下返回)? Something else? 还有吗

Peppering your code with try/catch statements only to crash the app isn't productive. 用try / catch语句添加代码只会使应用程序崩溃不会提高生产力。 The CLR already takes care of that for you. CLR已经为您解决了这一问题。 And you've got AppDomain.UnhandledException to generate decent information to diagnose the cause. 并且您已经有了AppDomain.UnhandledException来生成体面的信息来诊断原因。

Only in the very specific case that you have to clean up something, say a file that you don't want to keep laying about, should you consider writing a try/catch. 仅在非常特殊的情况下,您必须清理某些内容,例如不想保留的文件,才考虑编写try / catch。 Which in itself is a very iffy requirement, there is no guarantee whatsoever that your catch block will execute. 这本身是一个非常棘手的要求,无法保证您的catch块将执行。 It will not when the exception is nasty like StackOverflowException or ExecutionEngineException. 如果异常讨厌,例如StackOverflowException或ExecutionEngineException,则不会。 Or the more common reason that programs don't clean up after themselves, somebody tripping over the power cord or killing the process from Task Manager. 或更常见的原因是程序无法自行清理,有人在电源线上绊倒或杀死了任务管理器中的进程。

you are supposed to only use try/catch when you will actually handle the exception and not just report & log it and then crash the application 您应该仅在实际处理异常时才使用try / catch,而不仅仅是报告和记录异常,然后使应用程序崩溃

I agree with the first part, although I would add that adding logging at the tier boundaries is valuable when you may not have control over the calling tier. 我同意第一部分,尽管我会补充说,当您可能无法控制调用层时,在层边界添加日志记录很有价值。 eg I log all exceptions that occur in a Web Service at the top method to ensure I have logging on the server since debug info (stack trace, etc) does not always cross comm layers gracefully 例如,由于调试信息(堆栈跟踪等)并不总是优雅地跨越通讯层,因此我以最上面的方法记录了Web服务中发生的所有异常,以确保我已登录服务器

In your particular example I would check for "exceptional" conditions where you can but let other exception occur "naturally". 在您的特定示例中,我将检查“例外”条件,在该条件下您可以让其他例外“自然”发生。 For your specific examples: 对于您的特定示例:

  • argument (IDs[]) being null, 参数(IDs [])为null,
  • failure to establish an SQL connection, 无法建立SQL连接,
  • failure to execute a specific SQL query. 无法执行特定的SQL查询。

For the first one, I would check for null arguments for one reason: A NullReferenceException gives you no context about the cause of the exception, other that where it occurs. 对于第一个,我会检查null的参数为一个原因:一个NullReferenceException让你没有关于异常的原因,其他的是它所出现的上下文。 I much prefer to check for null and then throw a new ArgumentNullException exception since you can add which argument is null. 我更喜欢检查null ,然后引发新的ArgumentNullException异常,因为您可以添加哪个参数为null。 You may still need to do some digging to find out why it's null but it saves you a lot of time in debugging. 您可能仍需要进行一些挖掘,以找出为什么它为null的原因 ,但这可以节省大量的调试时间。

SQL Exceptions can typically bubble up naturally, since they have decent error information in them (eg "undeclared variable '@arg'" ) SQL异常通常会自然冒泡,因为它们中包含不错的错误信息(例如"undeclared variable '@arg'"

I've recently began reading up on this topic myself. 我最近开始自己阅读有关此主题的内容。 My basic understanding is: 我的基本理解是:

  1. Only catch an exception if you plan to handle it. 仅在计划处理时捕获异常。
  2. Overuse of try/catch can lead to exception swallowing and/or the loss of valuable stack trace information and can lead to maintainability issues (what if you decide to standardize your errors/logging?). 过度使用try / catch可能会导致吞咽异常和/或丢失有价值的堆栈跟踪信息,并可能导致可维护性问题(如果您决定标准化错误/记录该怎么办?)。 Instead use try/finally or using blocks to implement clean up. 而是使用try / finally或使用块来实施清理。
  3. Catch exceptions at the boundaries via a global exception handler. 通过全局异常处理程序在边界捕获异常。
  4. Use AppDomain.UnhandledException for exactly what the name implies: logging unhandled exceptions. 准确地使用AppDomain.UnhandledException来表示名称:记录未处理的异常。 If you do not log these you'll only find a CLR "Windows Error Reporting" entry in the log viewer and a few dump files that are really of no use to you. 如果您不记录这些,则只会在日志查看器中找到CLR“ Windows错误报告”条目,并找到一些确实对您没有用的转储文件。 It's always a good idea to utilize AppDomain.UnhandledException so if your application does crash you know why. 利用AppDomain.UnhandledException总是一个好主意,因此,如果您的应用程序崩溃了,您就会知道原因。

It's important to note that "handling" an exception doesn't necessarily mean clean up or retroactive logic. 重要的是要注意,“处理”异常并不一定意味着清除或追溯逻辑。 Handling could simply mean formatting an error to something more user-friendly or to hide a sensitive stack trace you wouldn't want just anyone to see. 处理可能只是意味着将错误格式化为更用户友好的格式,或者隐藏了您不希望任何人看到的敏感堆栈跟踪。 I routinely log a detailed error and return a formatted one. 我通常记录一个详细的错误,并返回一个格式化的错误。

Again, this is just what I've gathered initially. 同样,这就是我最初收集的内容。 Below are some sources: 以下是一些来源:

Good Exception Management Rules of Thumb 良好异常管理经验法则

Understanding and Using Exceptions 了解和使用异常

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Application.ThreadException 与 AppDomain.UnhandledException - Application.ThreadException vs AppDomain.UnhandledException AppDomain.UnhandledException与RegisterApplicationRecoveryCallback - AppDomain.UnhandledException vs. RegisterApplicationRecoveryCallback 在模块化表单应用程序中使用AppDomain.UnhandledException - Use AppDomain.UnhandledException in modular forms application 应该同时使用 AppDomain.UnhandledException 和 Application.DispatcherUnhandledException 吗? - Should use both AppDomain.UnhandledException and Application.DispatcherUnhandledException? The AppDomain.UnhandledException未捕获BackgroundWorker _异常 - BackgroundWorker _ Exception not caught by The AppDomain.UnhandledException 在AppDomain.UnhandledException处理程序中获取例外对象 - Get excepting object in AppDomain.UnhandledException handler AppDomain.UnhandledException的UnhandledExceptionMode.ThrowException - UnhandledExceptionMode.ThrowException for AppDomain.UnhandledException 在多线程环境中使用AppDomain.UnhandledException - Using AppDomain.UnhandledException in a multithreaded environment 如何处理C#AppDomain.UnhandledException - How to handle C# AppDomain.UnhandledException AppDomain.UnhandledException应该在哪里订阅? - Where should AppDomain.UnhandledException be subscribed to?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM