TIdTCPServer зависает при подключении во второй раз - PullRequest
0 голосов
/ 07 января 2012

Я использую TIdTCPClient для получения списка файлов, все работает хорошо, но когда я закрываю клиентское приложение и снова открываю его, я не получаю никакого события на TCPServer onExecute, хотя 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;

1 Ответ

3 голосов
/ 07 января 2012

Вы не защищаете свой критический раздел от исключений. Когда клиент отключается, исключение будет вызвано либо 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;
...