如何退出工作线程 QThread 的事件循环

naw*_*bgh 1 c++ qt qthread

我正在编写一个带有按钮的应用程序来启动/停止工作线程(实现QThread)。工作线程每隔几毫秒就会持续调度一个作业。为了终止工作线程,我从 GUI 线程调用worker.quit()worker.exit(0)也不起作用)方法并等待finished信号被触发。

问题是即使finished信号被触发,线程也不会终止。

这是一个最小的例子:https : //gist.github.com/NawfelBgh/941babdc011f07aa4ab61570d7b88f08

最小示例的屏幕截图

编辑

我对发生的事情的解释是错误的:工作线程正在终止,但该方法iter正在主线程中执行,如@sergey-tachenov 所述,并从代码生成的日志中确认:

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;
Run Code Online (Sandbox Code Playgroud)

我切换到不依赖于s的不同设计QTimer。但是我没有将其作为答案提交,因为这个问题的标题是“如何退出工作线程 QThread 的事件循环”。

Ser*_*nov 5

线程终止。只有您的计时器不在您启动的线程中运行,而是在主线程中运行,这就是它没有停止的原因。这是因为它默认使用排队连接,并且线程对象存在于创建它的线程中,该线程是主线程。要解决这个问题:

  • 千万不能继承QThread。除非您想实际扩展QThread的功能,否则这通常是一个坏主意。
  • 创建一个单独的工作对象,继承QObject.
  • 使用moveToThread给工人对象移动到创建的线程。它会导致它的所有插槽在线程中实际触发。如果您使用默认或排队连接,那就是。

QThread文档提供关于一个很好的例子(第一个)。

请注意,如果您确实想使用线程提供的数据来更新 GUI,则必须以某种方式将该数据正确发布到 GUI 线程(可能使用emit排队连接),而不是尝试直接从线程更新 GUI。如果您想访问共享数据,您可能需要使用 来保护它QMutex,而不是像使用共享计数器那样。