【问题标题】:Another TIdTCPServer deadlock situation另一个 TIdTCPServer 死锁情况
【发布时间】:2011-10-20 18:51:02
【问题描述】:

我遇到了一个已知问题:IdTCPServer 在尝试停用它时挂起。我已经阅读了很多关于此类问题的文章,并且我知道发生了死锁。但我很难理解究竟是哪个代码导致了问题。我的应用程序甚至没有窗口,因此对 VCL 组件的同步调用不是原因。有 2 个事件处理程序 OnConnect 和 OnExecute。问题出现在 OnConnect 中。代码:

TMyServer = class
...
private
FServer: TIdTCPServer;
...
end;

TMyServer.ServerConnect(AContext...);  //onconnect
begin
  try
    if not Condition then
    begin
      ...
      AContext.Connection.Disconnect;
      Stop;
    end
    else Start;
  except
    on E: Exception do
      if E is EIdException then raise;
      ...  
  end;

TMyServer.Start;
begin
  ...
  FServer.active := true;
  FServer.StartListening;
  ...
end;

TMyServer.Stop;
begin
  ...
  FServer.StopListening;
  FServer.Active := false;
  ...
end;

TMyServer.ServerExecute(AContext...);  //onexecute
begin
  LLine := AContext.Connection.IOHandler.ReadLn;
  case (LLine) of
  ...
  end;
end;

ServerExecute 的代码比较大,这里就不贴了。此外,我认为问题不在于它。
当客户端连接到服务器并且 Condition 为 false 时,服务器尝试断开此客户端并挂在行上 FServer.Active := false;
我已经从代码中排除了所有日志记录(我认为问题出在线程访问日志文件中)。所以在事件处理程序中只有计算,没有任何东西会导致死锁)。我读过关于重新提出 Indy 异常的信息,但这对我也没有帮助。
我将不胜感激任何帮助和解释,因为我认为我不完全理解这种情况的目的。

【问题讨论】:

    标签: delphi deadlock delphi-xe indy


    【解决方案1】:

    您正试图从其中一个事件处理程序中停用服务器。这就是您的代码死锁的原因。

    Active 属性设置为 False 会终止所有正在运行的客户端线程并等待它们完全终止。 OnConnectOnDisconnectOnExecute 事件在这些线程的上下文中触发。所以你最终会得到一个试图等待自己并死锁的线程。

    要让服务器安全地自行停用,您必须异步执行此操作,例如使用TIdNotify 类,例如:

    uses
      ..., IdSync;
    
    TMyServer.ServerConnect(AContext...);  //onconnect
    begin
      try
        if not Condition then
        begin
          ...
          AContext.Connection.Disconnect;
          TIdNotify.NotifyMethod(Stop);
        end
        else
          TIdNotify.NotifyMethod(Start);
      except
        on E: Exception do
          if E is EIdException then raise;
          ...  
      end;
    end;
    

    顺便说一句,您不需要手动调用StartListening()StopListening() 方法。 Active 属性设置器会在内部为您执行此操作。

    【讨论】:

    • 非常感谢雷米。你的回答让我明白了一切。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 2018-06-10
    • 1970-01-01
    相关资源
    最近更新 更多