I am using TIdTCPClient to get a file list all works well but when i close the client application and open it again i don’t receive any event on TCPServer onExecute though the TIdTCPClient successfully connects to it and i am not able to send the file list.
What am i doing wrong ?
Some code :
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;
You are not protecting your critical section from exceptions. When the client disconnects, an exception will be raised by either
ReadLn()orWriteLn()(depending on timing) to terminate the thread for that client. The next time theOnExecuteevent is called for a different thread, the critical section will still be locked and cannot be re-entered again, deadlocking your code. Add atry/finallyto your code to guard against that, eg:With that said, why are you using a critical section to begin with? The code you showed is thread-safe by itself, it does not need to be protected from concurrent access:
Alternatively: