为什么我的信号不触发没有Qt::D irectConnection的插槽?

Why don't my signals fire slots without Qt::DirectConnection?

本文关键字:irectConnection 插槽 Qt 信号 我的 为什么      更新时间:2023-10-16

我有一个主类,它启动一个执行单个操作的线程。我正在尝试捕捉线程操作何时完成。

主类:

// .h
class MainClass : public QObject
{
    Q_OBJECT
public:
    QThread thread;
// ...
public slots:
    void onFinish();
}
// .cpp
void MainClass::startThread()
{
    thread = new QThread();
    worker = new Worker();
    worker->moveToThread(thread);
    connect(thread, SIGNAL(started()), worker, SLOT(process()));
    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    connect(worker, SIGNAL(finished()), this, SLOT(onFinish()));
    // connect(worker, SIGNAL(finished()), this, SLOT(onFinish()), Qt::DirectConnection);
}
void MainClass::onFinish()
{
    std::cout << "Finished!" << std::endl << std::flush;
}

线程的Worker类:

// .h
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = 0);
    ~Worker();
public slots:
    void process();
signals:
    void finished();
}
// .cpp
void Worker::process()
{
    // ...Do stuff...
    emit finished();
}

执行startThread不打印"Finished!"为什么?

我注意到,如果我将Qt::DirectConnection添加到连接到onFinish()的行(如在注释行中),则打印消息。但是,如果我想在主类的线程中执行onFinish()动作,我能做些什么呢?

编辑1

此外,似乎finished() -> quit()连接也不起作用,因为如果我调用thread->isFinished()thread->isRunning(),在主线程睡眠后确保线程任务完成,我分别获得falsetrue

编辑2

因为它也可能是相关的,这里是main.cpp:

int _tmain(int argc, _TCHAR* argv[])
{
    QCoreApplication a(argc, argv);
    std::unique_ptr <MainClass> mc = std::make_unique <MainClass>();
    mc->startThread();
    mc->thread->wait();
    return a.exec();
}

乍一看,我觉得连接的顺序很重要。deleteLater()插槽应该总是最后一个方法。

connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), this, SLOT(onFinish()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

Sitenode - QRunnable您可以考虑使用QRunnable,它是为短时间运行的任务/作业而设计的。您可以将它们与QObject或QFuture/QFutureWatcher组合在一起,以便在它们完成时获得通知。

<标题>更新1

你的主事件循环永远不会开始,看起来你想在任务完成时退出应用程序。我不认为这是一个很好的实现,但这些修改应该为您工作:

int _tmain(int argc, _TCHAR* argv[])
{
    QCoreApplication a(argc, argv);
    std::unique_ptr<MainClass> mc = std::make_unique<MainClass>();
    mc->startThread();
    // do not wait!
    // let the main-event-loop handle events -> a.exec()
    // and quit() application by signal/slot
    return a.exec();
}
void MainClass::startThread()
{
    thread = new QThread();
    worker = new Worker();
    worker->moveToThread(thread);
    connect(thread, SIGNAL(started()), worker, SLOT(process()));
    connect(worker, SIGNAL(finished()), this, SLOT(onFinish()));
    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), qApp, SLOT(quit()));
}