tidtcpserver.active = false死锁(Delphi2007 / indy10)

时间:2010-07-31 08:37:24

标签: multithreading delphi delphi-2007 indy indy10

我遇到了一些代码问题,这些代码是由现在离开我们公司的开发人员编写的,代码实现了一个响应基于XML协议的tcpserver。这似乎在我们的测试环境中工作得非常好,但是有一两个客户在应用程序关闭时遇到问题。

我已经将此跟踪到了调用tidtcpserver.active = false时看似死锁的内容。我已经知道,其中一个连接步骤可以对主线程进行同步调用,而主线程正在等待连接线程终止,从而导致死锁。

我已经在使用tidthreadsafestringlist将数据传递给主线程进行处理,而我需要从主线程中调用一个过程,我创建了一个tidnotify后代来执行此操作。任何人都可以想到要寻找的其他东西。


我一直在检查异常处理,

这就是我在onexecute事件中所拥有的

try
  // code to handle connection including tidnotify etc....
except
  on E:Exception do
  begin
    if (e.InheritsFrom(EIdSilentException) = False) then
      TXMLTraceNotify.XMLTrace('TCPServerExecute: ' + E.Message,ttProblem, FTraceProc);
    raise; //we must raise all exceptions for indy to handle them.
  end;

端;


以下是我如何使用TS-stringlist

声明。

public
  TransactionStrings: TIdThreadSafeStringList;

它在构造函数中创建并在析构函数中销毁。

这就是我在tcpserver的上下文中添加它的方式。

  TransactionStrings.Add(newTrans.AsString);

这就是我在主应用程序线程

的上下文中从中读取的内容
slXMLTrans := TStringList.Create;
try
  slTemp := FCustomXMLServer.TransactionStrings.Lock;
  try
    slXMLTrans.Assign(slTemp);
    slTemp.Clear;
  finally
    FCustomXMLServer.TransactionStrings.Unlock;
  end;

  if slXMLTrans.Count > 0 then
  begin
    for i := 0 to Pred(slXMLTrans.Count) do
      TAbstractTerminal.ProcessXMLTrans(slXMLTrans[i]);
    slXMLTrans.Clear;
  end;
finally
  slXMLTrans.Free;
end;

我认为这是使用它的正确方法,但我等待你的评论。

1 个答案:

答案 0 :(得分:0)

将Active属性设置为False时的死锁是一个经典的,经常讨论的问题,当错误地使用TIdTCPServer时。服务器死锁的唯一方法是连接线程未正确终止。这可能是由于主线程忙于停用服务器时将operaton与主线程同步引起的,在这种情况下,使用TIdNotify可以消除任何此类死锁条件。

但是,这不是阻止连接线程终止的唯一方法。另一种可能性是,如果您的服务器事件处理程序中有异常处理,则会阻止Indy的内部通知被处理。这可能会导致失控的线程继续运行,但永远不会知道它们需要停止。如果要捕获代码中的异常,请确保重新抛出任何EIdException派生的异常,并让服务器在内部处理它们。