3

我正在尝试在一个单独的线程中执行一些工作,并在工作完成后停止该线程。

我已经建立了这样的连接

thread.connect( workerClass, SIGNAL( finished() ), SLOT( quit() ) );

但是当我发出 finished() 信号时,永远不会调用 quit() 插槽。命令行不显示与失败连接相关的任何警告。

我创建了一个简单的测试项目来缩小问题范围,并且得到了相同的行为:

测试类.h:

#ifndef TESTCLASS_H
#define TESTCLASS_H
class TestClass : public QObject
{
    Q_OBJECT
public:
    TestClass() { }
signals:
    void finished();
public slots:
    void doWork();
}
#endif // TESTCLASS_H

测试类.cpp:

#include "TestClass.h"
#include <QtCore/QDebug>
void TestClass::doWork()
{
    qDebug() << "Starting";
    for( long i = 0; i < 1000000000; i++ );
    qDebug() << "Done";
    emit finished();
};

和 main.cpp:

#include <QtCore/QCoreApplication>
#include <QtCore/QThread>
#include "TestClass.h"

int main( int argc, char* argv[] )
{
    QCoreApplication a( argc, argv );

    TestClass testClass;
    QThread testThread;

    testClass.moveToThread( &testThread );

    testThread.connect( &testClass, SIGNAL( finished() ), SLOT( quit() ) );
    testClass.connect( &testThread, SIGNAL( started() ), SLOT( doWork() ) );

    testThread.start();
    testThread.wait();

    return 0;
}

所以这就是我期望发生的事情:

  1. 一旦testThread.start()被处理,线程的run()函数就会被调用,该函数在内部调用exec()并启动一个事件循环。此外,它会发出一个started()信号。
  2. testClass有它的doWork()插槽被调用。
  3. 完成TestClass::doWork()后,它会发出一个finished()信号。
  4. 的事件循环testThread接收信号并将其转发到其quit()插槽
  5. testThread.wait()线程结束时从等待中返回。

步骤 1-3 工作,我得到了qDebug()输出。问题出在第 4 步:信号被触发并转发到某个事件循环(我对其进行了一点调试,但无法弄清楚它被触发到了哪个事件循环),但quit()从未调用过该插槽。

我究竟做错了什么?

PS:请不要建议子类化QThread,我尝试这种方式的全部目的是因为我想避免子类化QThread。

4

2 回答 2

5

我认为问题在于您实际上没有在场景中运行 Qt 事件循环。如果您替换testThread.wait()a.exec()(启动 Qt 事件循环),您应该会看到您的信号/插槽得到正确处理。

如果您希望应用程序在线程完成后退出,您可以使用 QCoreApplication 的quit()插槽来执行此操作。

于 2011-09-15T15:06:51.343 回答
1

我遇到了同样的问题并找到了答案。这是我的问题: QThread.wait() 函数有什么用?

要解决您的问题,您不需要运行 a.exec(),您需要做的是,而不是调用尝试向应用程序的事件循环发送信号的 quit()(这显然不是存在),你必须直接调用它。

因此,对于您的代码,请删除以下行:

testThread.connect( &testClass, SIGNAL( finished() ), SLOT( quit() ) );

而不是:

emit finished();

采用:

this->thread()->quit();

多田...问题解决了。经验教训:不要尝试通过 qt 信号槽机制从其中退出工作线程,因为您的信号不会到达它们应该到达的位置(您的工作线程的事件循环),但它们最终会在创建改为线程。您永远不知道该线程在做什么,以及它的事件循环是否正在运行,无论如何这对您的工作线程不应该有任何关系......相反,直接调用退出。

于 2013-11-19T19:40:11.257 回答