如何等待主线程中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
相关产品推荐
相关产品推荐

