我有一个服务器每 0.1 秒发送一次它的状态。我使用此代码访问 UI 并在客户端程序上显示结果。
procedure TModules.TCPServerExecute(AContext: TIdContext);
begin
Buffer:= AContext.Connection.IOHandler.ReadLn();
TIdNotify.NotifyMethod( ServerExecute );
end;
但是有些数据包没有收到ServerExecute
。我更改了代码并使用了TIdSync.SynchronizeMethod
. 问题解决了:
procedure TModules.TCPServerExecute(AContext: TIdContext);
begin
Buffer:= AContext.Connection.IOHandler.ReadLn();
TIdSync.SynchronizeMethod( ServerExecute );
end;
我在这个网站上读到 TIdSync.SynchronizeMethod 可能会产生死锁。所以我想知道有什么问题TIdNotify.NotifyMethod
。我还看到一个建议使用 aTimer
来同步 UI 并且不使用 Notify() 或 Synchronize() 方法的答案。
另外我必须提到该程序在内部完成了其余的工作ServerExecute
。
如您所见,我将代码缩小到以下内容。我必须提到,我使用以下代码执行了该程序,但它已经存在问题并且没有得到预期的结果:
procedure TModules.ServerExecute;
var
I: Word;
tmp, Packet, Cmd:string;
CheckSum: Boolean;
begin
//try
frmDiag.DataLog.Lines.Add(Buffer);
{ExplodeStr(Buffer, Cmd, Packet);
if Cmd='status' then
begin
//ExplodeStr(Packet, Cmd, Packet);
if trim(Packet)='' then
raise Exception.Create('Empty packet received.');
//Prepare for log
{tmp:='';
for I := 1 to Length(Packet) do
begin
if (Ord(Packet[I])>=48) and (Ord(Packet[I])<=122) then
tmp:=tmp+Packet[I]+''
else
tmp:=tmp+IntToStr(Ord(Packet[I]))+'';
end;
//frmITCAMain.Memo1.Lines.Add(Packet);
CheckSum:=ParsePackets(Packet);
IntersectionsList.Int.CallNotifier; //Call the notifier to execute assigned proc
if frmLoader.Visible=true then
with frmLoader do
begin
if
//(Packet[1]='X') or //Server responce
(Packet[1]<>'l') and (Packet[1]<>'s') and (Packet[1]<>'e')and //ignore general packet
(
(Req[1]<>'f') //Only receive ACK
or
((Req[1]='f')and( (Req[2]='m')or(Req[2]='a')or(Req[2]='b') ))
or
( //Receive Data+ACK
(Req[1]='f')and( (Req[2]='g')or(Req[2]='h')or(Req[2]='p')or(Req[2]='j') )
and
(Packet[1]<>'k') //Ignore ACK
)
)
then
begin
if CheckSum then
begin
Res:= Packet;
Confirm;
end
else
begin
if Packet='n' then //Checksum failure
Fail
else
SendPacket; //Resend.
//lblError.Visible:=true;
end;
end;
end;
if (Packet[1]='g') or (Packet[1]='h') or (Packet[1]='p') or
(Packet[1]='j') or (Packet[1]='k') then
frmIntDetails.memReceived.Lines.Text:=tmp;
end
else if Cmd='server' then
begin
with frmLoader do
begin
if Visible=false then exit;
Res:= Packet;
if Copy(Res, 1, 2)='ok' then
Confirm
else
Cancel;
end;
end
else
ClientLog.Add(Buffer);
except on E: Exception do
begin
if E.Message='Connection Closed Gracefully.' then
ClientLog.Add('X:Connection closed(Gracefully)')
else
ClientLog.Add(E.Message+' Buffer="'+Buffer+'"');
end;
end;
//Memo2.Lines.Add( FloatToStr(TimeStampToMSecs(DateTimeToTimeStamp(Now))));
}
end;
frmDiag.DataLog
是一个TMemo
组件。
例如frmDiag.DataLog
,下面的列表是我预期的结果(以下字符串是从带有TIdSync.SynchronizeMethod
解决方案的 Datalog 组件中提取的):
status:l77770000140000
status:eFFFF20000140
status:s0000
status:s0000
status:s0000
status:s0000
status:l00005555140000
status:eFFFF20000140
status:s0000
status:s0000
status:s0000
status:s0000
status:l77770000140000
status:eFFFF20000140
但相反,我得到了这个结果:
status:eFFFF20000140
status:eFFFF20000140
status:s0000
status:s0000
status:s0000
status:s0000
status:s0000
status:s0000
status:s0000
status:s0000
status:s0000
status:l00005555140000
status:l77770000140000
如您所见,订单未得到满足。
我必须得到一个status:l77770000140000
类似的数据包,然后是status:eFFFF20000140
一个然后是 4 status:s0000
,依此类推。
@Remy 我稍微更改了您的代码:
TMyNotify = class(TIdNotify)
protected
FBuffer: String;
FMethod: TThreadMethod;
procedure DoNotify; override;
public
constructor Create(const ABuffer: String; AMethod: TThreadMethod);
end;
///......
{ TMyNotify }
constructor TMyNotify.Create(const ABuffer: String; AMethod: TThreadMethod);
begin
inherited Create;
FBuffer := ABuffer;
FMethod := AMethod;
end;
procedure TMyNotify.DoNotify;
begin
inherited;
FMethod;
//Destroy;
end;
这就是我现在调用 ServerExcecute 的方式:
procedure TModules.TCPServerExecute(AContext: TIdContext);
begin
Buffer:= AContext.Connection.IOHandler.ReadLn();
TMyNotify.Create(Buffer, ServerExecute).Notify;
// ServerExecute;
// TIdNotify.NotifyMethod( ServerExecute );
// TIdSync.SynchronizeMethod( ServerExecute );
end;