Delphi TIdTCPServer在第二次连接时卡住

Delphi TIdTCPServer在第二次连接时卡住,delphi,indy,Delphi,Indy,我正在使用TIdTCPClient获取文件列表,所有这些都可以正常工作,但是当我关闭客户端应用程序并再次打开它时,我在TCPServer OneExecute上没有收到任何事件,尽管TIdTCPClient成功连接到它,并且我无法发送文件列表 我做错了什么 一些代码: procedure TTaifun.csConnected(Sender: TObject); begin cs.IOHandler.WriteLn('FILE_LIST|NOW'); //Sending a request

我正在使用TIdTCPClient获取文件列表,所有这些都可以正常工作,但是当我关闭客户端应用程序并再次打开它时,我在TCPServer OneExecute上没有收到任何事件,尽管TIdTCPClient成功连接到它,并且我无法发送文件列表

我做错了什么

一些代码:

procedure TTaifun.csConnected(Sender: TObject);
begin
  cs.IOHandler.WriteLn('FILE_LIST|NOW'); //Sending a request to server for the files
  fname := cs.IOHandler.ReadLn(nil); //Got the file names
  files := ExplodeString(fname,'|'); // Parse the files
end;

procedure TTaifun.svExecute(AContext: TIdContext);
var
  cmds, flist: TStringList;
  i: Integer;
  tmp: string;
  FS : TFileStream;
begin
  CSection.Enter; //Enter critical section
  cmds := ExplodeString(AContext.Connection.IOHandler.ReadLn(nil), '|'); 
  try
    if cmds[0] = 'FILE_LIST' then //Check command received
    begin
      flist := TStringList.Create;
      flist.LoadFromFile(MyPath + 'files.dat');
      tmp := '';
      for i := 0 to flist.Count - 1 do
      begin
          tmp := tmp + flist[i] + ',' + GetFileSize(flist[i]) + ',' +
          BoolToStr(FileExists(MyPath + 'Thumbs\' +
          ChangeFileExt(ExtractFileName(flist[i]), '.thb')),true) + '|'; //Do some parsing
      end;
      AContext.Connection.IOHandler.WriteLn(tmp); //Send the string
    end
 finally
  CSection.Leave; //Leave critical section
 end;
end;

您没有保护您的关键部分不受异常的影响。当客户端断开连接时,
ReadLn()
WriteLn()
(取决于时间)将引发异常,以终止该客户端的线程。下次为其他线程调用
OnExecute
事件时,关键部分仍将被锁定,无法再次输入,从而导致代码死锁。在代码中添加一个
try/finally
,以防止出现这种情况,例如:

procedure TTaifun.svExecute(AContext: TIdContext); 
var 
  ...
begin 
  CSection.Enter; //Enter critical section 
  try
    ...
  finally
    CSection.Leave; //Leave critical section 
  end;
end; 
既然如此,为什么要从关键部分开始呢?您显示的代码本身是线程安全的,不需要对其进行并发访问保护:

procedure TTaifun.svExecute(AContext: TIdContext);     
var     
  cmds, flist: TStringList;     
  i: Integer;     
  tmp: string;     
begin     
  cmds := ExplodeString(AContext.Connection.IOHandler.ReadLn, '|');      
  if cmds[0] = 'FILE_LIST' then //Check command received     
  begin     
    tmp := '';     
    flist := TStringList.Create;     
    try
      flist.LoadFromFile(MyPath + 'files.dat');     
      for i := 0 to flist.Count - 1 do     
      begin     
        tmp := tmp + flist[i] + ',' + GetFileSize(flist[i]) + ',' +     
          BoolToStr(FileExists(MyPath + 'Thumbs\' +     
          ChangeFileExt(ExtractFileName(flist[i]), '.thb')),true) + '|'; //Do some parsing     
      end;
    finally
      flist.Free;
    end;     
    AContext.Connection.IOHandler.WriteLn(tmp); //Send the string     
  end;
end;
或者:

procedure TTaifun.svExecute(AContext: TIdContext);     
var     
  cmds, flist: TStringList;     
  i: Integer;     
begin     
  cmds := ExplodeString(AContext.Connection.IOHandler.ReadLn, '|');      
  if cmds[0] = 'FILE_LIST' then //Check command received     
  begin     
    flist := TStringList.Create;     
    try
      flist.LoadFromFile(MyPath + 'files.dat');     
      for i := 0 to flist.Count - 1 do     
      begin     
        flist[i] := flist[i] + ',' + GetFileSize(flist[i]) + ',' +     
          BoolToStr(FileExists(MyPath + 'Thumbs\' +     
          ChangeFileExt(ExtractFileName(flist[i]), '.thb')),true); //Do some parsing     
      end;
      flist.Delimiter := '|';
      flist.StrictDelimiter := True;
      AContext.Connection.IOHandler.WriteLn(flist.DelimitedText); //Send the string     
    finally
      flist.Free;
    end;     
  end;
end;

请参阅作者对此的评论。它与TIdHTTP相关,但可能会让您了解问题所在。对你的Delphi和Indy版本进行精确化,并提供一些代码,这将有助于人们愿意回答你的问题。真的,你在这里问了足够多的问题,知道如果你不提供更多细节,没有人能帮助你。。。比如…,哦,我不知道,也许是一些代码?@Marjannema我不喜欢你的态度,我很好奇你现在是否有解决办法。很难。我不喜欢你老是问问题,等别人问更多的细节,然后再提供足够的信息让别人帮助你。在您添加的代码中,您不知道TTaifun是从何而来的,也不知道它是服务器端还是客户端,也不知道其他可能帮助您的东西。虽然我可以做一个受过教育的任务,但我不会去打扰,我不应该去…@Marjannema不要打扰我舒尔不会错过任何东西:)