如何吞下所有异常并保护我的应用程序不会崩溃?

Nan*_* HE 10 c# exception-handling

我发现了几个C#应用程序崩溃,以响应错误条件,如obj = nullobj.member = null.很多时候,来自3rdPartyApp界面的obj.并导致3rdPartyApp和MyCsApp崩溃在一起.

如何在所有可能的区域添加异常处理,以便我的应用程序可以在这些灾难性的情况下生存?向所有地方添加try-catch并从这种情况中恢复是一项挑战.

我怎样才能以现实,可靠和防弹的方式实现这一目标?

[更新:工业自动化控制]

结构体:

GUI(asp.net,c ++) - RuntimeApp(C++) - MyCsApp(cs) - 3rdPartyApp(Cs)

正常程序:

  1. HostApp - (通过以太网Cabele连接) - MyCsApp
  2. 操作员 - GUI - RuntimeApp - MyCsApp

异常情况:

  1. 一些非标准的操作程序;
  2. 发生了一些硬件问题;
  3. 等等

我最好处理所有异常情况.最重要的是,我必须考虑如何从情况中恢复过来.

Joh*_*ers 19

希望抓住每一个例外,随处可见.

您希望防止异常"泄漏"应用程序的较低层,直到它们可以杀死应用程序或破坏它.

但是,防止腐败需要的不仅仅是捕获异常.您将不得不确保应用程序始终可以安全地在可能引发异常的每个位置进行中断.这可能意味着您需要清理复杂的操作.例如:

ComplexBuilder cb = new ComplexBuilder();
try
{
    cb.AddOperation(...);  // Once building starts,
    cb.AddOperation(...);  // it's not safe to use cb
    cb.AddOperation(...);
}
catch (SpecificException ex)
{
    cb.Cleanup();          // until it's cleaned up
}

// Now safe to access cb, whether or not an exception was thrown
Run Code Online (Sandbox Code Playgroud)

我最近遇到了一个态度相似的应用程序.有一个被认为是"重要"的应用程序.当那个"重要"的事情发生时,还有其他的东西应该发生,但被认为是"不重要".这个想法是,如果"不重要"部分有例外,那么"重要"部分就必须继续下去.

发生的事情是由于某种原因尝试读取资源失败了.返回null而不是字符串资源.这导致了ArgumentNullException一个String.Format电话.这导致异常被刚刚继续的代码捕获.

但是在第一个异常和最后一个异常之间,已经分配了一个对象,并且已经设置了对该对象的引用.但由于例外,设置引用从未发生过.结果是我看到了NullReferenceException四个堆栈级别,两个.csproj文件远离实际问题发生的地方.

因此,当您谈到捕获异常以便程序可以继续时,您需要记住,通过捕获所有这些异常,程序的控制流程会发生巨大变化.实际上,它可能会发生很大变化,以至于您无法再确定程序是否可以继续执行.

  • 丁丁丁丁 我们有一个胜利者. (2认同)

Sco*_*ith 7

这是许多开发人员无法获得的.当你的异常catch-all被击中时,你的应用程序已经崩溃了.什么意外发生了,这意味着你的代码没有预料到的是,事情很可能是在一个不确定的状态(即你不能确定到底有多少有问题的功能,在产生异常的点完成的,你不知道写了多少数据,在硬件中设置了什么位等等.继续下去是否安全?你应该试着保存用户的数据吗?谁知道!

当您达到这个高级别的捕获量时,您还没有阻止您的应用程序崩溃.你只是决定在那一点上如何应对崩溃.您可以提供与标准不同的消息:

此应用程序执行了非法操作

...但是你的自定义信息会更好吗?

我们在没有预先安排的情况下关闭了计划外维护,但请放心,这与这个优秀的软件中的缺陷无关

...?


t0m*_*13b 3

首先治愈疾病是有意义的,找出它导致崩溃的原因,确保代码崩溃是因为obj = null或类似的原因 - 使用异常处理并吞下所有异常只是掩盖问题......这就是它不被使用的地方为了!听起来好像有很多代码味道会触发崩溃 - 保护应用程序免于崩溃并不是处理它的正确方法,只会让事情变得更糟......

好的,您可以按照 John Saunders 和 pm100 的建议来执行此操作...但要以某种方式处理它,看看根本原因是什么,不要将其视为“神奇的银弹”,在一天结束时,代码与第三方应用程序交互需要彻底调试......

例如

对象 foo = null;
酒吧巴兹;

// ....
// foo 现在由第三方应用程序设置

if (foo != null && foo is bar) baz = (bar)foo as bar;

如果(巴兹!=空){

  // 继续,baz 是 'bar' 类型的合法实例

}别的{

  // 优雅地处理它或抛出*用户定义的异常*

}

注意如何使用“as”来检查“foo”是否属于“bar”实例的正确类型 - 现在与此进行比较,这是典型的代码味道......

对象 foo = null;
酒吧巴兹;

// foo 现在由第三方应用程序设置 - 您真的确定它是非空吗?
// 它真的是“BAR”类型吗?

巴兹=富;// 碰撞!砰!猛击!克朗奇!