我有一个运行长批处理的应用程序,可能会抛出许多异常.如果在批处理中的一个项目期间抛出非关键异常,我只想记录并继续,这样我们可以稍后解决问题,同时让其他批处理项继续.
一些例外,例如OutOfMemoryException,对整个应用程序来说是毁灭性的,这些我想重新抛出,以便它们冒泡到全局异常处理程序,它将记录错误并停止应用程序.
所以我的问题是,是否有一个合理的简短列表,我可以在我的下级异常处理程序中重新抛出,同时抑制(在记录之后)其他所有内容?
谢谢!
编辑:稍微详细说明,这是我的程序的基本结构
foreach(var item in longItemList)
{
try
{
bigDynamicDispatchMethod(item);
}
catch(Exception ex)
{
logException(ex);
}
}Run Code Online (Sandbox Code Playgroud)
可能会抛出大量异常,因为这个循环几乎是我应用程序的顶级.我项目中99%的代码都在调度方法之后.我在较低级别进行合理的异常处理,但是bug仍在继续运行,并且我不想在抛出异常后停止批处理中的其他无关进程.
试图找到可以在我的应用程序中的其他地方抛出哪些异常似乎是一项艰巨的任务,而且似乎更容易获得关键异常的黑名单.
有没有更好的方法来构建我的应用程序来处理这个?我愿意接受建议.
当我关闭最后一个窗口时,我的应用程序中出现了未处理的异常:
PresentationFramework.dll中出现未处理的"System.NullReferenceException"类型异常
附加信息:未将对象引用设置为对象的实例.
只有在应用程序的生命周期中,我通过我设置的某个进程打开子窗口时才会出现这种情况.该窗口存在于另一个程序集中,该程序集在运行时使用MEF动态加载,然后使用Castle进行实例化.如果我然后调用某个方法,它会创建一个新的STA线程并打开一个WPF对话框窗口.
一些警告:
调用堆栈是:
PresentationFramework.dll!MS.Internal.Controls.ConnectionPointCookie.Disconnect()
PresentationFramework.dll!MS.Internal.Controls.ConnectionPointCookie.Finalize()
Run Code Online (Sandbox Code Playgroud)
有没有人见过这个,或者有人知道如何调试这个?奇怪的是,没有调用堆栈,它在程序退出时正确发生.
传统观点认为我们应该只捕获我们期望的特定异常类型:
try
{
int.Parse(str); //I am aware of TryParse(), this is just for the sake of example
}
catch (FormatException ex)
{
Console.WriteLine (ex);
}
catch (OverflowException ex)
{
Console.WriteLine (ex);
}
Run Code Online (Sandbox Code Playgroud)
但是,有时我们并不关心发生了哪个异常(只要它不是致命的),可能是因为我们只是想让用户知道发生了错误.在这些情况下,我们可以这样做:
try
{
Foo();
}
catch (Exception ex)
{
if (IsCriticalException(ex))
{
Environment.FailFast("System Error", ex);
}
Console.WriteLine ("Error running Foo: {0}", ex);
}
Run Code Online (Sandbox Code Playgroud)
在哪里IsCriticalException可以类似地实施System.ClientUtils.IsCriticalException.由于以下几个原因,我一般都赞成这种方法:
ArgumentException.有些方法甚至不能静态地知道它们可以抛出哪些异常,因为它们动态地加载其他模块/插件.据推测,他们可以用他们自己已知的例外情况包装所有这些"外部"例外,但我相信并非所有例外都有.这种方法的批评者认为方法的例外是其合同的一部分.如果抛出的异常不是本合同的一部分,我们应该假设其状态已损坏.我们还会在方法中发现一个错误(因为我们已经吞下了意外的异常,否则我们就不会发现这个错误).然后我们可以将这个bug传递给框架的开发人员,这是一个胜利 - 特别是如果这些开发人员在我们公司,所以我们"帮助自己"可以这么说.
我承认,批评者提出了有效的观点,但我觉得他们有点理想主义.实际上,我认为通用的非致命异常捕获在很多情况下都是有意义的.我有道理吗?
相关阅读:
我知道有些异常类型无法在catch块中捕获,例如StackOverflowException在.NET 2.0中.我想知道哪些其他例外不适合捕获,或者与不良做法有关.
我想使用这个异常类型列表的方法是每次Exception在catch块中使用时检查它:
private static readonly Type[] _exceptionsToNotCatch = new Type[] { typeof(StackOverflowException) };
// This should never throw, but should not swallow exceptions that should never be handled.
public void TryPerformOperation()
{
try
{
this.SomeMethodThatMightThrow();
}
catch (Exception ex)
{
if (_exceptionsToNotCatch.Contains(ex.GetType()))
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
我认为我没有提供一个很好的例子.这是试图在传达一个人的意思时试图做出一个小例子的问题之一.
我自己从不抛出异常,并且我总是捕获特定的异常,只捕获Exception如下:
try
{
this.SomeMethodThatMightThrow();
}
catch (SomeException ex)
{
// This is safe to ignore.
}
catch (Exception ex)
{
// Could be some kind of system or …Run Code Online (Sandbox Code Playgroud) 我刚刚开始研究现有的大项目.其中一些包含遗留代码.
我被要求编写一个组件(将在同一个进程中运行),该组件应在发生致命错误或发生情况时发出警报并重新启动服务器.
例如,当抛出OutOfMemoryException时,我应该警告客户端,然后重新启动服务器.问题是,搜索所有现有的Try-catch块然后编辑并向其catch块添加新代码将是困难和耗时的.更重要的是,新的程序员可以添加一个新的try-catch块,如果捕获了OutOfMemoryException则忘记警告.
您是否知道如何监视/侦听OutOfMemoryException(以及类似的异常),而无需查找和编辑(并可能添加)每个现有和未来的Try-catch块?
我正在使用.Net 4.
编辑: