TIdTCPServer 第二次连接时卡住
我正在使用 TIdTCPClient 获取文件列表,一切正常,但是当我关闭客户端应用程序并再次打开它时,尽管 TIdTCPClient 成功连接到它,但我在 TCPServer onExecute 上没有收到任何事件,并且我无法发送文件列表。
我做错了什么?
一些代码:
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;
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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您没有保护您的关键部分免受异常影响。当客户端断开连接时,
ReadLn()
或WriteLn()
(取决于时间)将引发异常,以终止该客户端的线程。下次为不同的线程调用OnExecute
事件时,临界区仍将被锁定并且无法再次重新进入,从而使代码陷入死锁。在代码中添加try/finally
来防止这种情况发生,例如:话虽如此,为什么要使用临界区呢?您展示的代码本身是线程安全的,不需要保护它免受并发访问:
或者:
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 theOnExecute
event is called for a different thread, the critical section will still be locked and cannot be re-entered again, deadlocking your code. Add atry/finally
to 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: