处理不可预见的异常

Handling of unforseen exceptions

如果我想写入文件并处理 IOExceptions(以防文件被写保护),我会执行以下操作:

try
{
    var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
    using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)
    {    
        sw.WriteLine(entry);
    }
}
catch (IOException ex)
{
    return ex.Message;
}

如果我遇到意外异常,我的程序会崩溃,用户会报告错误,我会修复它。这就是我想要的。

所以我应该添加另一个捕获点:

catch (Exception)
{
    throw;
}

这会有什么不同吗?最佳做法是什么?

嗨,如果您想抛出应用程序崩溃的异常,请执行此操作

 try
{
    var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
    using (StreamWriter sw = new StreamWriter(fs, Encoding.Default)
    {    
        sw.WriteLine(entry);
    }
}
catch (IOException ex)
{
    throw ex;
}

但我认为你不应该让它崩溃而只显示错误消息

在 catch 调用函数中写入文件,然后 return 消息并显示给用户。希望对你有帮助

 public static void WriteCustomLog(string msg)
            {
                FileStream fs = null;
                StreamWriter sw = null;
                FileStream fs1 = null;
                StreamWriter sw1 = null;
                try
                {
                    //check and make the directory if necessary; this is set to look in the application
                    //folder, you may wish to place the error log in another location depending upon the
                    //the user's role and write access to different areas of the file system
                    if (!System.IO.Directory.Exists(Application.StartupPath + "\Log\"))
                        System.IO.Directory.CreateDirectory(Application.StartupPath + "\Log\");

                    string date = DateTime.Now.ToString("dd_MM_yyyy");

                    //check the file
                    fs = new FileStream(Application.StartupPath + "\Log\Log" + date + ".txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
                    sw = new StreamWriter(fs);
                    sw.Close();
                    fs.Close();

                    //log it
                    fs1 = new FileStream(Application.StartupPath + "\Log\Log" + date + ".txt", FileMode.Append, FileAccess.Write);
                    sw1 = new StreamWriter(fs1);
                    sw1.Write(DateTime.Now.ToString() + " Message: " + msg + Environment.NewLine);
                    sw1.Write("Date/Time: " + DateTime.Now.ToString() + Environment.NewLine);
                    sw1.Write("=======================================================" + Environment.NewLine);

                }
}

然后处理对象 未测试

您可以捕获异常,然后在内部检查异常的类型。然后决定如何处理。

catch(Exception ex)
{
  if(ex.InnerException is IOException )
  {
    // do  something
  }
 else
  {
   // do something else
  }
}

您可以使用 AppDomain.UnhandledException 事件。

也许您也想使用 Application.ThreadException 活动。

So should I add another catch like

(几乎)从来没有。至少不在堆栈跟踪中。它只会让您的应用程序更难阅读。

大多数应用程序都有入口点。例如,如果您编写 windows 服务,您通常会为该工作创建线程。您可以在其中添加 catch (Exception) 以防止它们崩溃。

所以我的意思是,在大多数情况下,您应该只在顶层使用 catch all,以防止您的应用程序难以阅读或维护。

当一切都失败时

有时,如果您在顶层的某处忘记了一个 catch all,您的应用程序无论如何都会崩溃。

然后您想要使用 AppDomain.UnhandledException,因为它在 .NET 中为所有应用程序类型调用。然而,它不会让您阻止应用程序崩溃,而只是记录您的应用程序即将崩溃的原因。

如果您正在编写 UI 基于 winforms 的应用程序,您可以改用 Application.ThreadException。但是,它只会处理 UI 线程上的异常。因此,您仍然需要使用 AppDomain.UnhandledException 来记录在其他线程上抛出的异常。

.NET 中的所有主要 library/framework 都有自己的方法来允许您处理未处理的异常。您需要在您正在使用的库的文档中查找它。

catch(Exception)
{ 

    throw;    
} 

什么都不做。异常随其原始堆栈跟踪一起抛出,并且不执行任何其他操作。您可以捕获一般异常,这使您可以选择提供额外的日志记录 and/or 向用户显示更好的错误消息

catch(Exception ex)
{ 
    LogError(ex);
    if (weDontCareThisWasntImportantAnyWay)
    {
        if (theUserShouldBeNotifiedAtThisPoint)
        {
            SomehowNotifyTheUser(ex);
        }
    }
    else
    {
        //Maybe something else cares
        throw;    
    }
} 

您应该处理意外异常,但是 catchthrow 是多余的 - 无论如何都会从您的方法中抛出异常。你应该做的是问自己这个问题,"What can I do about this exception here?"。对于IOException,答案很明确。您希望异常可能发生,可以处理它,并且可以继续。如果是泛型Exception,这可能不是处理它的地方。

如果发生异常时需要运行一些代码,为其添加catch。如果您的代码在该异常之后无法继续,请将异常抛出到更高层(不处理它或使用 throw),并在调用层次结构的更高层添加处理程序。或许可以上级处理,继续执行。否则,您的应用程序将需要退出。

您可以在程序的入口点添加顶级 try/catch 块,并在那里捕获未处理的异常。您的应用程序甚至可以在此之后继续(但是,在任何重要的应用程序中,这都不太可能,因为此时抛出的异常有多高)。要捕获任何其他未处理的异常(例如那些在线程中未处理的异常),您可以向 AppDomain.CurrentDomain.UnhandledException 添加一个处理程序。然而,这是不可恢复的——您的应用程序将在之后直接退出。 UnhandledException 处理程序是在发生异常之前执行某些异常操作的最后机会,通常会记录它以诊断出了什么问题。

哦,另外,如果您正在编写 WPF 应用程序,则可以在 App.xaml 中为 Application 上的 DispatcherUnhandledException 事件添加一个处理程序。这会捕获 WPF 调度程序线程中发生的任何未处理的异常。与上面的 AppDomain 处理程序不同,可以继续调度程序线程上未处理的异常 - 如果应用程序可以继续,您可以将事件参数中的 IsHandled 设置为 true