我目前在客户端(IdTCPClient)和服务器(IdTCPServer)之间有稳定的代码,它们按计划完成。但是,当我从按钮的OnClick事件调用以下函数时,服务器会冻结。
var
SendStream: TMemoryStream;
FileStream: TFileStream;
List: TList;
I: Integer;
begin
try
//Load
FileStream := TFileStream.Create(Path, fmOpenRead);
FileStream.Position := 0;
//Place into stream
SendStream := TMemoryStream.Create;
SendStream.Write(Header, SizeOf(Header)); //This works; supporting code ommitted for brevity
SendStream.CopyFrom(FileStream, FileStream.Size);
SendStream.Position := 0;
TIdContext(fTCP.Contexts.LockList[0]).Connection.IOHandler.Write(SendStream, 0, True);
fTCp.Contexts.LockList;
if Assigned(Self.fServerOnSync) then Self.fServerOnSync(SizeOf(Header)) //event handler for main form
finally
FileStream.Free;
SendStream.Free;
end;
我猜这与死锁线程有关,但对于我的生活,我不知道它为什么会发生。
另外,如果我将上述代码封装在包含IdTCP服务器的某个类中,该服务器将调用我的自定义fServerOnSync事件,那么这个线程是否安全?
干杯, 阿德里安
答案 0 :(得分:1)
您正在调用fTCp.Contexts.LockList()
两次,但您根本没有调用fTCp.Contexts.UnlockList()
,因此每当尝试访问Contexts
列表时,服务器就会陷入僵局。锁定后需要解锁列表,例如:
var
SendStream: TMemoryStream;
FileStream: TFileStream;
List: TList;
I: Integer;
begin
FileStream := TFileStream.Create(Path, fmOpenRead or fmShareDenyWrite);
try
SendStream := TMemoryStream.Create;
try
SendStream.Write(Header, SizeOf(Header));
SendStream.CopyFrom(FileStream, FileStream.Size);
SendStream.Position := 0;
List := fTCP.Contexts.LockList;
try
TIdContext(List[0]).Connection.IOHandler.Write(SendStream, 0, True);
finally
fTCP.Contexts.UnlockList;
end;
if Assigned(fServerOnSync) then fServerOnSync(SizeOf(Header));
finally
SendStream.Free;
end;
finally
FileStream.Free;
end;
...
end;