我有一个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
本质上的作用,但有没有办法避免在没有例外的情况下施加的开销?)
答案 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)
在异常事件中,您可以执行任何操作,包括记录异常。 如果你想为异常添加一些特殊内容,可以仍然有一个本地try..except并修改E.Message然后调用raise。然后将使用修改后的消息调用全局异常处理程序。