【发布时间】:2015-08-31 16:56:22
【问题描述】:
我有一个在 delphi XE 中开发的客户端/服务器应用程序,它使用 TIdTcpClient (Indy10) 相互通信。
大多数时候一切正常,唯一的问题是当我杀死服务器端时,客户端引发异常,以某种方式一直引发到用户,它首先显示我的自定义异常:
然后在空白处显示一个错误对话框,如下所示:
这是应该覆盖原始异常的代码,我创建的对话框显示和另一个对话框(上图)紧随其后。
constructor EtvdNTierTcpException.Create(const AException: Exception);
const
error = 'error message';
var
AIdSocketError: EIdSocketError;
sMessage, sConnectionPoint: string;
begin
if AException is EIdSocketError then
begin
AIdSocketError := AException as EIdSocketError;
if StvdDefaultSession.tvdConnectionPoint = cpSqlProxy then
sConnectionPoint := FtvdNTierSqlProxy
else
sConnectionPoint := FtvdNTierSqlServer;
case AIdSocketError.LastError of
// 10054: Connection reset by peer
10054: self.Message := ExtractFileName(application.exename) + error + DateToStr(Now) + ' ' + TimeToStr(Now) + ' (' + AIdSocketError.ClassName + ')' + 'Connection for dataset fail at(10054)';
// 10061: Connection refused
10061: self.Message := ExtractFileName(application.exename) + error + DateToStr(Now) + ' ' + TimeToStr(Now) + ' (' + AIdSocketError.ClassName + ')' + 'Connection for dataset fail at(10061)';
else
self.Message := error + DateToStr(Now) + ' ' + TimeToStr(Now) + ' (' + AIdSocketError.ClassName + ')' + 'Connection for dataset fail at('+IntToStr(AIdSocketError.LastError)+')';
end;
end;
inherited;
end;
我尝试使用CheckForGraceFulDisconnect(false);,但它没有任何区别,关于如何阻止 Indy 显示此错误的任何想法?
这就是引发上述异常的方式:
function TtvdNTierDataSet.tvdStmtExecute(const AStmt: string): Boolean;
begin
try
tvdStmtExecute := False;
// check we are still connected to the server
if tvdSession.tvdConnect then
begin
tvdStmtExecute := True;
// write the SQL Statement to the server
tvdWriteOutput;
end;
except
on E: Exception do
begin
// re-raise the exception
raise EtvdNTierTcpException.Create(E);
end;
end;
end;
【问题讨论】:
-
您不应覆盖原始代码。你在主线程中使用 TCPClient 吗?您应该使用单独的线程。最后,您是否尝试过 TCPClient 操作的 try/except ?您应该捕获任何异常。
-
您没有显示从哪里调用
EtvdNTierTcpException.Create(),或者在什么代码中引发了原始异常。在下一次访问底层套接字之前,Indy 不会在断开连接时引发异常。而修改原始异常通常是错误的做法。假设EtvdNTierTcpException是Exception的后代,请考虑使用捕获原始异常的try/except并使用Exception.RaiseOuterException()引发您自己的异常,该异常将原始异常捕获为其InnerException而无需修改它。 -
@Icaro:那你为什么要修改原来的
EIdSocketError?引发您自己的异常只会丢弃先前的异常,因为您正在捕获它(或者您是吗?您仍然没有显示引发异常的实际代码)。 -
@Icaro:您的异常构造函数正在修改原始
EIdSocketError异常的Message属性,而不是您自己异常的Message属性。留下原件。从中读取,不要修改它。您的异常Message为空白,这就是用户看到空白消息框的原因。 -
@Icaro:如果您希望异常处理程序有机会看到触发您的异常的原始异常:
on E: Exception do begin Exception.RaiseOuterException(EtvdNTierTcpException.Create(E)); end;,您可以选择将原始异常捕获到异常的InnerException属性中。跨度>
标签: delphi tcp delphi-xe indy indy10