1

我遇到了一些由现已离开我们公司的开发人员编写的代码的问题,该代码实现了一个响应基于 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;

我认为这是使用它的正确方法,但我等待您的意见。

4

1 回答 1

0

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

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

于 2010-08-02T21:09:30.103 回答