C#中异常处理中的嵌套异常处理

5

我知道这可能有点奇怪,但毕竟怀疑就是怀疑... 在以下情况下会发生什么...

(接下来的内容需要IT技术背景)

private void SendMail()
{
    try
    {
        //i try to send a mail and it throws an exception
    }
    catch(Exception ex)
    {
        //so i will handle that exception over here
        //and since an exception occurred while sending a mail
        //i will log an event with the eventlog

        //All i want to know is what if an exception occurs here
        //while writing the error log, how should i handle it??
    }
}

谢谢您。
8个回答

4

您可以通过错误日志记录方法轻松捕获错误。但是我个人不会这样做,因为错误的日志记录表明您的应用程序根本无法正常运行。

private void SendMail()
{
    try
    {
        //i try to send a mail and it throws an exception
    }
    catch(Exception ex)
    {
        WriteToLog();
    }
}

private void WriteToLog()
{
    try
    {
        // Write to the Log
    }
    catch(Exception ex)
    {
        // Error Will Robinson
        // You should probably make this error catching specialized instead of pokeman error handling
    }
}

+1 没错 - writeToLog 应该处理自己的异常(要么抑制,要么抛出) - Robben_Ford_Fan_boy

4
我个人建议在写入事件日志的调用周围再包装一层try\catch语句。
然而,最终取决于您的规格说明。如果将故障写入事件日志对系统至关重要,则应允许其被抛出。但是,根据您的示例,我怀疑这不是您想要做的事情。

6
顺便说一下:"嘿,老兄,我听说你喜欢捕获异常,所以我在你的 try-catch 中加了一个 try-catch,这样你就能在捕获时再次捕获了。" :) - ANeves
嘿,David, 我也相信你是正确的,我们应该让第二个异常被抛出,因为如果在那里抛出异常,那就意味着问题存在于客户端机器上...... 而我们的首选是与我们的应用程序相关的异常...... 但是,我该如何找出我的应用程序发生了什么错误,因为既没有发送邮件,也没有记录错误? 有什么建议吗,伙计? - Shrewdroid
如果它引起运行时异常,您可以使用一些工具(如Dr Watson)来检查转储 - 再次建议避免这种情况。对于嵌入式的try\catch,我会尝试将其写入文件作为最后的希望。这样,您就有了3个级别的通知:邮件在顶部,事件日志在其次,然后是日志文件 - 但是如果调用日志文件失败,则让其抛出异常。 - Robben_Ford_Fan_boy

1

每个异常只有在try-catch块内部才会被捕获。你可以嵌套try-catch,但通常不是一个好主意。


正确的,嵌套try-catch块感觉“不干净”。然而,也没有什么其他办法。 - Dercsár

0

我个人使用一个简单的扩展方法来处理这种情况。

public static class MyExtentions
{
    public static void LogToErrorFile(this Exception exception)
    {
        try
        {
            System.IO.File.AppendAllText(System.IO.Path.Combine(Application.StartupPath, "error_log.txt"),
                String.Format("{0}\tProgram Error: {1}\n", DateTime.Now, exception.ToString()));
        }
        catch 
        { 
            // Handle however you wish
        }
    }
}

使用方法很简单:

try
{
   ...
}
catch(Exception ex)
{
   ex.LogToErrorFile();
}

然后你可以在扩展方法内部处理捕获的异常,或者干脆不捕获它并让它冒泡到顶部。我发现这种设计是一种简单、可重复的方式来处理整个应用程序中的异常。


0
你可以在你的catch块中添加一个try-catch块。

0

考虑到写入文件时可能出现的异常(权限、磁盘空间等),我建议不要在此处处理。如果第一次失败,很有可能您将无法写入事件日志以说明无法写入事件日志...

让它上升并由上层 try/catch 处理。


0

Chris S. 给出了最好的答案。在 catch 块中放置 try-catch 块很少是一个好主意,而且在你的情况下,它只会使你的代码变得混乱。如果你在这里检查是否成功写入日志文件,那么你将不得不在每个尝试写入日志文件的地方都这样做。你可以通过让所有单独的模块在处理这些模块内部的错误条件时都是自包含的来轻松避免这种不必要的代码重复。当发送邮件失败时,你可以在 catch 块内执行适当的操作来处理这种异常情况,例如:

  1. 处理你的邮件对象的内容
  2. 确保你的套接字已关闭
  3. 写入日志文件以记录错误

在你的 catch 块内,只需调用你定义的 API 来写入日志条目,然后忘记其他事情。在你的日志 API 内部,你应该处理任何与日志相关的异常情况(磁盘已满、没有写入文件的权限、找不到文件等)。你的邮件模块不需要知道日志记录是否成功,这个责任应该委托给日志记录模块。


0
  • 首先,我建议不要在catch块中捕获"Exception"。相反,对于邮件,在检查完所有有效性后,可以捕获特定的异常(如SmtpException),并进行有意义的处理(同时向用户发送友好的消息)。从代码中抛出异常并通知UI并不是一个坏主意。如果您的方法接受特定规格的输入,而这些规格未被满足,那么您的方法应该/可以抛出错误并告知用户。

  • 对于无法控制的异常,请使用全局异常处理,例如Web的Application_Error。 Getting Better Information on Unhandled Exceptions Peter Bromberg更好地解释了这一点。

  • 此外,对于任何您访问的特权资源,如事件日志,请确保您的程序集对其具有访问权限。

  • 有用的链接Build a Really Useful ASP.NET Exception Engine By Peter A. BrombergDocumenting Exceptional Developers By Peter A. Bromberg 对于Web应用程序,请查阅 Health monitoring Exception logging

  • 还有一件事,如果您的应用程序出现问题/抛出无法处理的错误,则最好让其优雅地崩溃并停止运行。处于不稳定状态的应用程序不是好主意。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接