Delphi - 关闭应用程序时终止所有线程(TThread)

4
我的应用程序是一个TCP/IP服务器,主线程只创建一次并一直监听。当新客户端连接时,主线程会创建TClientThread类型的新线程。但是没有正在运行的客户端线程列表,因为那会使我的应用程序变得有点复杂...是否有任何方法可以在所有线程上执行“终止”方法,即使线程正在忙碌中(在我的情况下,“忙碌”意味着它正在等待数据,其中设置的超时时间约为30秒...所以我必须无论如何杀死它,而不必等待)?简单关闭应用程序似乎无法在线程上运行“终止”方法,这导致FastMM报告内存泄漏...
3个回答

17

在关闭时出现的内存泄漏不需要担心 - 在返回控制权给操作系统之前释放内存是浪费时间且没有必要减慢应用程序退出速度。你真正需要做的就是确保所有数据已保存,所有进程间句柄(如信号量和互斥锁)正确释放并退出即可。

对于通知客户端,你可以采取类似以下策略:

  • 将所有处理客户端的线程添加到某个列表中(创建、销毁和迭代时适当加锁)
  • 使客户端线程在终止时从列表中删除自己,并在列表中最后一个项目被删除时设置事件(手动重置事件,例如TEvent在SyncObjs中)如果服务器正在关闭
  • 在本来会长时间阻塞的例程中引入轮询(例如使用select或等效的超时)或其他类型的中断(例如SO_RCVTIMEO/SO_SNDTIMEO),监视Terminated属性
  • 在关闭时,锁定列表并遍历它,调用Terminate,然后等待事件被触发;当然,在迭代列表之前,应关闭添加项目到列表中的侦听套接字并确保其已关闭

事实上,线程需要被正确终止,以便让应用程序知道保存其客户端状态为断开连接...所以我需要知道如何做到这一点! - migajek
2
关于关闭时的内存泄漏,不用担心:也许这就是为什么每次关闭Delphi IDE时,我几乎总是遇到灾难性的故障。 - Tihauan
卸载包时是一个不同的问题,例如,包可能会被重复加载和卸载。至于为什么你在关闭时遇到IDE崩溃的问题,我没有更多的数据无法推测。 - Barry Kelly
1
在关闭时出现的内存泄漏确实是需要关注的问题。它们是一种信号,表明您的代码可能存在一些问题。您不能忽略它们,但是一旦您知道为什么和何时发生这些泄漏以及它们并不危险,您就可以接受它们。 - Tom Hagen

2
我使用一个全局的 KillThreadList:TList。 我在我的线程中进行监控,如下所示:
while (Not Terminated) do
begin
  inc(Inker);
  if (WaitForSingleObject(FTick, finterval) = WAIT_TIMEOUT) then
  Begin
    if Inker >= 10 then
    Begin
      ProcessTables;
      Inker := 0;
      sleep(1000);
    End;
    if KillThreadList.Contains(ThreadID) = True then Terminate;
  End;
end;

我还会在进程中测试KillThreadList,以便在安全的情况下让我退出它们。

我将OnTerminate事件传递给主线程,并在那里从KillList中删除ThreadID。我广泛使用这个模型,它从未让我失望过。

procedure TfrmProcessQualcommLocations.OnTerminateThread;
var
  ThreadID : Cardinal;
  i : integer;
  aStatusBar :TStatFrame;
begin
  ThreadID := (Sender as Tthread).ThreadID;
  for i := 0 to StatusBarList.Count -1  do
  Begin
    if StatusBarList.Items[i].ThreadID = ThreadID then
    Begin
      aStatusBar := StatusBarList.Items[i];
      KillThreadList.Extract(ThreadID);
      StatusBarList.Extract(aStatusBar);
      aStatusBar.Free;
      break;
    End;
  End;

  self.Refresh;
end;

在上述情况下,我也删除了一些GUI内容。
希望能对您有所帮助。 SpringerRider

"= True" 真是太棒了! - Nashev

2
看起来这篇文章可能会有所帮助。 如果您点击该链接,您将看到以下内容:
使用信号量在Delphi中进行编程,第2部分:连接池
作者:Cary Jensen
摘要:信号量用于协调多个线程和进程。本文介绍了TFixedConnectionPool类,它利用信号量提供多个线程对共享资源的同时访问。

信号量是一种同步构造,与 OP 面临的问题(在关闭时终止线程)几乎没有关系。 - jpfollenius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接