tidtcpserver.active = false 上出现死锁 (Delphi2007/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;
我认为这是使用它的正确方法,但我等待您的评论。
I am having a problem with some code that was written by a developer that has now left our company, the code implements a tcpserver that responds to an XML based protocol. This appears to be working absolutely fine in our test environment but one or two customers are having problems with application shutdown.
I have traced this to what appears to be a deadlock when tidtcpserver.active = false is called. I am already aware that a deadlock can be caused by one of the connection treads making a synchronised call to the main thread, whilst the main thread is waiting for the connection threads to terminate.
I am already using a tidthreadsafestringlist to pass the data to the main thread for processing, and where I need to call a procedure from the main thread I have created a tidnotify descendant to do this. can anyone think of anything else to look for.
I had already been checking the exception handling,
this is what i have in the onexecute event
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;
end;
Here is how i'm using the TS-stringlist
Declaration.
public
TransactionStrings: TIdThreadSafeStringList;
its created in the constructor and destroyed in the destructor.
this is how i'm adding to it in the context of the tcpserver.
TransactionStrings.Add(newTrans.AsString);
And this is how i'm reading from it in the context of the main application thread
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;
I think this is the correct way to use it but I await your comments.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
将 Active 属性设置为 False 时出现的死锁是不正确使用 TIdTCPServer 时的一个典型且经常讨论的问题。服务器死锁的唯一原因是连接线程未正确终止。这可能是由于主线程正忙于停用服务器时将操作同步到主线程造成的,在这种情况下,使用 TIdNotify 确实可以消除任何此类死锁情况。
但是,这并不是防止连接线程终止的唯一方法。另一种可能性是,如果您的服务器事件处理程序中有异常处理,则会阻止 Indy 的内部通知被处理。这可能会导致失控的线程继续运行,但永远不知道它们需要停止。如果您在代码中捕获异常,请确保重新抛出任何 EIdException 派生的异常并让服务器在内部处理它们。
Deadlocks when setting the Active property to False are a classic, and often discussed, issue when using TIdTCPServer incorrectly. The only way the server deadlocks is when the connection threads do not terminate correctly. That MAY be caused by synchronizing operaton to the main thread while the main thread is busy deactivating the server, in which case the use of TIdNotify would does eliminate any such deadlock conditions.
However, that is not the only way to prevent a connection thread from terminating. Another possibility is if your server event handlers have exception handling in them that is blocking Indy's internal notifications from being processed. That can cause runaway threads that keep running but never know that they need to stop. If you are catching exceptions in your code, make sure you re-throw any EIdException-derived exceptions and let the server handle them internally.