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