2010-07-31 28 views
1

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

我已经追踪到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; 

的情况下,我认为这是使用了正确的方式,但我在等待着您的意见。

回答

0

将Active属性设置为False时发生死锁是错误地使用TIdTCPServer时的经典问题,并且经常被讨论。服务器死锁的唯一方式是连接线程不能正确终止。这可能是由于主线程正在忙于停用服务器时将operaton同步到主线程所致,在这种情况下,使用TIdNotify将消除任何此类死锁情况。

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

+0

试图在此处张贴代码,但将其置于答案中 – MikeT 2010-08-03 16:14:14