如何退出 worker QThread 的事件循环
How to quit the event loop of a worker QThread
我正在编写一个带有按钮的应用程序 start/stop 工作线程(实现 QThread
)。
工作线程每隔几毫秒就会持续调度一个作业。
要终止工作线程,我从 GUI 线程调用 worker.quit()
(worker.exit(0)
也不起作用)方法并等待 finished
信号被触发。
问题是即使触发了 finished
信号,线程也没有终止。
这是一个最小的例子:
https://gist.github.com/NawfelBgh/941babdc011f07aa4ab61570d7b88f08
编辑
我对发生的事情的解释是错误的:工作线程正在终止但是方法iter
正在主线程中执行,如@[=所说38=] 并从使用代码生成的日志中确认:
void run() {
std::cout <<"From worker thread: "<<QThread::currentThreadId() << std::endl;
...
void iter() {
std::cout <<"From thread: "<<QThread::currentThreadId() << std::endl;
...
void MainWindow::on_pushButton_clicked()
{
std::cout <<"From main thread: "<<QThread::currentThreadId() << std::endl;
我切换到不依赖 QTimer
的 different design。但我没有提交它作为答案,因为这个问题的标题是“如何退出一个工人 QThread 的事件循环”。
线程已终止。只有你的计时器不在你启动的线程中运行,而是在主线程中运行,这就是它没有停止的原因。这是因为它默认使用排队连接,并且线程对象存在于创建它的线程中,即主线程。要修复它:
- 做不子类
QThread
。除非您想实际扩展 QThread
的功能,否则这通常不是一个好主意。
- 创建一个继承
QObject
. 的单独的worker对象
- 使用
moveToThread
将worker对象移动到创建的线程中。它会导致它的所有插槽实际在线程中触发。如果您使用默认或排队连接,即。
The QThread
docs 提供了一个很好的例子(第一个)。
请注意,如果您确实想使用线程提供的数据来更新 GUI,则必须以某种方式将该数据正确发布到 GUI 线程(可能使用 emit
和排队的连接),而不是尝试直接从线程更新 GUI。如果你想访问共享数据,你可能需要用 QMutex
来保护它,而不是像你对共享计数器所做的那样。
我正在编写一个带有按钮的应用程序 start/stop 工作线程(实现 QThread
)。
工作线程每隔几毫秒就会持续调度一个作业。
要终止工作线程,我从 GUI 线程调用 worker.quit()
(worker.exit(0)
也不起作用)方法并等待 finished
信号被触发。
问题是即使触发了 finished
信号,线程也没有终止。
这是一个最小的例子: https://gist.github.com/NawfelBgh/941babdc011f07aa4ab61570d7b88f08
编辑
我对发生的事情的解释是错误的:工作线程正在终止但是方法iter
正在主线程中执行,如@[=所说38=] 并从使用代码生成的日志中确认:
void run() {
std::cout <<"From worker thread: "<<QThread::currentThreadId() << std::endl;
...
void iter() {
std::cout <<"From thread: "<<QThread::currentThreadId() << std::endl;
...
void MainWindow::on_pushButton_clicked()
{
std::cout <<"From main thread: "<<QThread::currentThreadId() << std::endl;
我切换到不依赖 QTimer
的 different design。但我没有提交它作为答案,因为这个问题的标题是“如何退出一个工人 QThread 的事件循环”。
线程已终止。只有你的计时器不在你启动的线程中运行,而是在主线程中运行,这就是它没有停止的原因。这是因为它默认使用排队连接,并且线程对象存在于创建它的线程中,即主线程。要修复它:
- 做不子类
QThread
。除非您想实际扩展QThread
的功能,否则这通常不是一个好主意。 - 创建一个继承
QObject
. 的单独的worker对象
- 使用
moveToThread
将worker对象移动到创建的线程中。它会导致它的所有插槽实际在线程中触发。如果您使用默认或排队连接,即。
The QThread
docs 提供了一个很好的例子(第一个)。
请注意,如果您确实想使用线程提供的数据来更新 GUI,则必须以某种方式将该数据正确发布到 GUI 线程(可能使用 emit
和排队的连接),而不是尝试直接从线程更新 GUI。如果你想访问共享数据,你可能需要用 QMutex
来保护它,而不是像你对共享计数器所做的那样。