如何安全地停止线程任务?
问题
Qt 中如何安全停止一个正在运行的后台任务?
回答
核心原则
- 协作式取消:任务周期性检查“是否请求中断/停止”,在安全点有序退出。
- 避免强杀:硬终止可能造成资源泄漏、死锁或状态不一致。
常见手段
QThread::requestInterruption()
+isInterruptionRequested()
:
void Worker::doWork() {
while (...) {
if (QThread::currentThread()->isInterruptionRequested()) break;
// ... 执行一小步 ...
}
emit finished();
}
// 请求停止
thread->requestInterruption();
thread->quit();
thread->wait();
- 原子标志:
std::atomic_bool stop{false};
// 循环中检查 stop.load();外部设置 stop.store(true)
- 可中断等待:
- 使用带超时的等待函数(如
waitFor...
),周期性返回检查中断。 - I/O 或阻塞读:关闭套接字/管道唤醒阻塞,再走正常清理路径。
UI 收尾与资源释放
- 在
finished
槽中回收资源、更新 UI 状态。 - 使用
deleteLater()
销毁归属于子线程的对象;线程用quit()+wait()
收尾。
线程池/QtConcurrent 任务
- 使用
QFuture
: - Qt6:
QFuture::cancel()
/isCanceled()
;Qt5 需自管标志。 QFutureWatcher::finished()
在 UI 线程通知,做善后。
反例与风险
- 直接
terminate()
:不可取,可能中断在关键区,导致数据破坏。 - 在 UI 线程等待未可中断的长任务:界面卡死;改用后台执行 + 协作式取消。