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

时间:2009-07-29 21:32:22

标签: delphi terminate fastmm tthread

我的应用程序是一个tcp / ip服务器,主线程仅创建一次&一直在听。当新客户端连接时,主线程创建TClientThread类型的新线程。但是没有运行客户端线程的列表,因为这会使我的应用程序有点复杂...有没有办法在所有线程上执行“terminate”方法,即使线程忙(在我的情况下“忙”)意味着它正在等待数据,超时设置大约是30秒......所以无论如何我都要杀掉它,而不是等待。)? 简单的关闭应用程序似乎不会在线程上运行“terminate”方法,最终会导致FastMM报告的内存泄漏......

3 个答案:

答案 0 :(得分:16)

关机时的内存泄漏无需担心 - 在将控制权返回给操作系统之前解决内存泄漏的麻烦是浪费时间并且不必要地减慢应用程序退出的速度。您真正需要做的就是确保已保存所有数据,并正确释放所有进程间句柄(如信号量和互斥量),然后退出。

对于通知客户,您可以做的最好的策略是这样的策略:

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

答案 1 :(得分:2)

Sounds like this article may help

点击该链接后会看到什么:

  

在Delphi中使用信号量,第2部分:   连接池

     

作者:Cary Jensen

     

摘要:信号量用于   协调多个线程和   流程。信号量提供   多个线程同时进行   访问共享资源是   突出显示   TFixedConnectionPool类描述   在这篇文章中。

答案 2 :(得分: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事件传递给Main线程并从那里删除了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