1

我目前在客户端(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 事件,这是否是线程安全的?

干杯,阿德里安

4

1 回答 1

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;
于 2012-07-24T06:55:56.020 回答