是否有一种有效的方法来防止程序没有尝试...除了?

时间:2015-10-13 03:28:10

标签: delphi exception

我有一个Delphi 6客户端 - 服务器应用程序,其中服务器本质上是:

initialize;
repeat
  try
    getInput;
    putOutput;
  except
    on e: exception do writeln(e.message);
  end
until false;

在开发过程中,错误(例如指针异常)很少见,但服务器可以继续运行。现在它正在生产中,服务器似乎已经调试了,并且很容易删除try...except,因为它会给服务器增加大量的执行开销,但是如果发生异常则会停止服务器

一个解决方案是让父进程简单地重启整个服务器,并且在重启时绕过初始化将有效地重现try...except完成的内容,但是不会有任何导致异常的记录,并且重启无论有没有初始化,实际上都会产生许多不必要的“状态”问题,特别是对于客户端连接。

是否有某种方法可以覆盖或修改异常处理,以便在异常发生时将其记录到某个地方(例如在系统事件日志或%errorlevel%中),然后程序退出并重新启动或(更好:)恢复,但是没有无所不包的try...except

的开销

理想的解决方案会记录异常,但会在repeat...until级别恢复执行。也许通过在某些可访问的全局中保存repeat的地址,然后进行任何异常来解除调用堆栈并在该保存的地址恢复? (我猜这是try..except本质上的作用,但有没有办法避免在没有例外的情况下施加的开销?)

3 个答案:

答案 0 :(得分:6)

扩展Serg的建议:

repeat
  try
    repeat
      getInput;
      putOutput;
    until false;
  except
    on e: exception do writeln(e.message);
  end
until false;

具有相同的行为,但将try .. except移到最里面的循环之外。

然而,如果这对性能有任何明显的影响,我会感到惊讶。

答案 1 :(得分:2)

扩展David和Sergs的建议......

如果您的循环的复杂性与发布的代码建议的一样低(或者可以降低到这样的简单程度)那么根据命令提供两个行为可能是切实可行的line切换到通过异常处理启用或禁用运行时错误。

在启动时解析命令行以确定操作模式并相应地设置指示符变量。例如使用枚举:

type
  TServerMode = (smHighThroughput, smDiagnostic);

var
  ServerMode: TServerMode;


if FindCmdLineSwitch('d') then
   ServerMode := smDiagnostic
else
   ServerMode := smHighThroughput;

如果命令行参数因任何原因不合适或不实用,您当然可以在配置文件或数据库表中使用设置。

然而,除此之外,您还能够以“高吞吐量”模式或“可恢复诊断”模式运行服务器,并且语法重复最少:

try
  case ServerMode of
    smDiagnostic     : repeat
                         try
                           getInput;
                           putOutput;
                         except
                           on e: Exception do .... // etc      
                         end;
                       until FALSE;

    smHighThroughput : repeat
                         getInput;
                         putOutput;
                       until FALSE;
  end;

except
  on e: Exception do .... // etc      
end;

请注意,即使在 HighThroughput 模式下,上述示例也会捕获有关导致服务器终止的任何异常的信息。 诊断模式记录所有异常但尝试保持服务器正常运行。

然后,您可以默认使用 HighThroughput 模式,并选择启用诊断模式,以防您需要诊断看起来异常不稳定的服务器。

说了这么多,我会尽力量化try..except对循环的影响,然后再竭力设计这个影响。

答案 2 :(得分:0)

  • 将ApplicationEvents放在应用程序的中心位置。
  • 实施OnException事件。
  • 删除本地尝试...除了删除开销。

在异常事件中,您可以执行任何操作,包括记录异常。 如果你想为异常添加一些特殊内容,可以仍然有一个本地try..except并修改E.Message然后调用raise。然后将使用修改后的消息调用全局异常处理程序。