C# 不可预见异常的处理

C# 不可预见异常的处理,c#,exception,try-catch,C#,Exception,Try Catch,如果我想写入文件并处理IOExceptions(如果文件是写保护的),我会执行以下操作: try { var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None); using (StreamWriter sw = new StreamWriter(fs, Encoding.Default) { sw.WriteLine(entry);

如果我想写入文件并处理
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调用函数中,写入文件,然后返回消息并显示给用户。希望能有帮助

 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);

                }
}
然后处理对象
未测试

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

catch(Exception ex)
{
  if(ex.InnerException is IOException )
  {
    // do  something
  }
 else
  {
   // do something else
  }
}
您可以使用该事件

也许你也想参加这个活动

那么,我应该添加另一个类似的捕获吗

(几乎)从来没有。至少不在堆栈跟踪中。这只会让你的申请更难阅读

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

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

当一切都失败时

有时,如果您忘记了顶层的某个地方,您的应用程序无论如何都会崩溃

然后,您希望在.NET中为所有应用程序类型调用时使用
AppDomain.UnhandledException
。但是,它不允许您阻止应用程序崩溃,只允许您记录应用程序即将崩溃的原因

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

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

catch(Exception)
{ 

    throw;    
} 
什么也不做。异常将与其原始堆栈跟踪一起引发,并且不会执行其他操作。您可以捕获一般异常,这使您可以选择提供额外的日志记录和/或向用户显示更好的错误消息

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

您应该处理意外的异常,但是带有
throw
catch
是多余的-无论如何,异常都会从您的方法中抛出。你应该做的是问自己这样一个问题,“我能为这个例外做些什么?”。对于
IOException
,答案很清楚。您期望异常可能发生,可以处理它,并且可以继续。对于一般的
异常
,这里可能不是处理它的地方

catch(Exception ex)
{
  if(ex.InnerException is IOException )
  {
    // do  something
  }
 else
  {
   // do something else
  }
}
如果发生异常时需要运行某些代码,请为其添加一个
catch
。如果代码在该异常后无法继续,请将异常抛出更高级别(通过不处理它或使用
抛出
),并在调用层次结构中向上添加处理程序。也许它可以在更高的层次上处理,并且可以继续执行。否则,您的应用程序将需要退出

您可以在程序的入口点添加顶级
try
/
catch
块,并在那里捕获未处理的异常。在此之后,您的应用程序甚至可以继续运行(但是,考虑到此时抛出的异常有多高,在任何非平凡的应用程序中都不太可能)。要捕获任何其他未处理的异常(例如,在线程中未处理的异常),可以将处理程序添加到。但是,这是不可恢复的-您的应用程序将在之后直接退出。
UnhandledException
处理程序是在异常发生之前对异常执行操作的最后一次机会,通常会记录异常以诊断出错的原因


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

我不希望应用程序在IOException上崩溃,因为我不希望应用程序在IOException上崩溃,除非它可能发生并因此处理它。这是关于我不排除的例外情况。我应该捕获它们并抛出还是什么都不做。因此,在异常中返回消息并显示给用户,然后编写带有错误的自定义日志(return ex.message;)这会重置堆栈跟踪为什么?您可以捕获(IOException),然后通过链接处理程序回退到Exception()。@kha:您没有注意到他检查了内部异常吗。您无法捕获它。@jgauffin问题是关于捕获IOException和调用方法时可能发生的其他类型的异常,这个答案是检查捕获所有异常的内部异常作为一种方法。这种方法是错误的:不是每个异常都有InnerException,也不是每个IOException都被重新抛出(事实上,如果重新抛出IOException是标准行为,我会感到惊讶)这意味着此解决方案不会处理导致异常的IOException,也不会将其作为另一种类型的异常与IOException对象的InnerException一起重新抛出。您也可以使用我们的服务,它为您处理所有集成。