【问题标题】:Delphi (Indy) Server Freezing on WriteDelphi(Indy)服务器在写入时冻结
【发布时间】:2012-07-24 05:55:03
【问题描述】:

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

干杯, 阿德里安

【问题讨论】:

  • 问:“Self.fServerOnSync()”到底是什么?
  • type TServerOnSync = procedure(HeaderSize: Integer) of Object;对不起;所有这些都包装在一个以 IdTCPServer 作为字段的类中。因此,当我实例化这个类时,我设置了这个事件。
  • 即使注释掉该行仍然会导致写入冻结:/

标签: delphi client-server indy


【解决方案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;

【讨论】:

  • 谢谢,这是一个愚蠢的错误,但仍然没有运气;仍然冻结。 :/ 客户是否需要对此做出响应才能使其正常工作? Atm 客户端未编程。
  • Indy 使用阻塞套接字,因此如果客户端没有在其端读取入站数据,最终套接字的内部发送缓冲区将填满,并且套接字将在服务器端阻塞等待客户端清空缓冲区。在这种情况下避免死锁的唯一方法是直接使用套接字 API 设置套接字级别的发送超时。 Indy 没有在其逻辑中实现发送超时。
猜你喜欢
  • 1970-01-01
  • 2017-02-15
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 2012-10-29
  • 1970-01-01
  • 2016-07-02
  • 2012-11-14
相关资源
最近更新 更多