You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何等待主线程中TThread异步队列事件完成而非移除?

如何等待TThread队列中的事件全部执行完毕?

方法1:用计数器+事件追踪任务完成

你可以通过维护线程安全的计数器,结合事件对象来追踪所有队列任务的完成状态,具体步骤如下:

  • 初始化一个计数器和事件对象,每次调用Queue时递增计数器;
  • 在队列任务的执行逻辑末尾递减计数器,当计数器归0时触发事件;
  • 关闭应用前,等待事件被触发,确保所有任务执行完毕。

示例代码:

var
  PendingQueueTasks: Integer;
  AllTasksDoneEvent: TEvent;

initialization
  PendingQueueTasks := 0;
  AllTasksDoneEvent := TEvent.Create(nil, False, False, '');

procedure QueueAndTrack(const ATask: TThreadProcedure);
begin
  TInterlocked.Increment(PendingQueueTasks);
  TThread.CurrentThread.Queue(nil, procedure
    begin
      try
        ATask();
      finally
        if TInterlocked.Decrement(PendingQueueTasks) = 0 then
          AllTasksDoneEvent.SetEvent;
      end;
    end);
end;

procedure WaitForAllQueuedTasks;
begin
  // 先主动处理一轮已排队的消息
  while TThread.CurrentThread.QueuedEventCount > 0 do
    Application.ProcessMessages;
  
  // 等待所有任务完成
  AllTasksDoneEvent.WaitFor(INFINITE);
end;

finalization
  AllTasksDoneEvent.Free;

方法2:循环处理消息直到队列为空

如果不需要精确追踪单个任务,也可以直接利用TThread的QueuedEventCount属性,循环触发主线程消息处理,直到队列中没有待执行的事件:

procedure WaitForAllQueuedEvents;
begin
  while TThread.CurrentThread.QueuedEventCount > 0 do
  begin
    Application.ProcessMessages;
    Sleep(10); // 短暂休眠降低CPU占用
  end;
end;

注意事项

  • 如果队列任务中会动态添加新的队列任务,需要确保等待逻辑能处理这种嵌套情况,避免遗漏新任务;
  • 在应用关闭阶段调用等待逻辑时,要确保主窗体和相关资源尚未被销毁,防止任务执行时访问无效内存;
  • 方法1中的计数器和事件必须保证线程安全,这里用TInterlocked类来操作计数器是关键。

内容的提问来源于stack exchange,提问作者Mike Versteeg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:01:36