QThread - 调用另一个线程的方法

Posted

技术标签:

【中文标题】QThread - 调用另一个线程的方法【英文标题】:QThread - Call a method of another thread 【发布时间】:2014-03-09 23:27:54 【问题描述】:

我正在尝试使用invokeMethod 调用另一个线程(不是Main)的方法。不幸的是,这会使应用程序在尝试执行 invokeMethod 时立即崩溃!

我是不是弄错了什么?

// main.cpp

#include <QtCore>
#include "entrypointclass.h"
int main(int argc, char *argv[])

    QCoreApplication a(argc, argv);

    qDebug() << a.thread()->currentThreadId() << " - Application started.";

    EntryPointClass entryPoint;
    entryPoint.runInNewThread();
    return a.exec();

//入口点.h

#ifndef ENTRYPOINTCLASS_H
#define ENTRYPOINTCLASS_H

#include "worker.h"
#include <QtCore>

class EntryPointClass : public QObject

    Q_OBJECT
public:
    EntryPointClass();
    ~EntryPointClass();
    void runInNewThread();
public slots:
    void timeoutExpired();
private:
    Worker* m_Worker;
    QThread* m_Thread;
;

#endif // ENTRYPOINTCLASS_H

//入口点.cpp

#include <QTCore>
#include "entrypointclass.h"
#include "Worker.h"

EntryPointClass::EntryPointClass()

    qDebug() << "EntryPointClass created";





EntryPointClass::~EntryPointClass()

    qDebug() << "EntryPointClass destroyed";


void EntryPointClass::runInNewThread()

    QThread* m_Thread = new QThread;
    Worker* m_Worker = new Worker();


    connect(m_Thread, SIGNAL(started()), m_Worker, SLOT(doSomething()));
    connect(m_Worker, SIGNAL(finished()), m_Thread, SLOT(quit()));
    connect(m_Thread, SIGNAL(finished()), m_Thread, SLOT(deleteLater()));
    connect(m_Thread, SIGNAL(finished()), m_Worker, SLOT(deleteLater()));

    QTimer* timer = new QTimer;
    timer->setSingleShot(true);

    //bool bOK = connect(timer, SIGNAL(timeout()), m_Worker, SLOT(closeWorker()), Qt::BlockingQueuedConnection);

    connect(timer, SIGNAL(timeout()), this, SLOT(timeoutExpired()));

    m_Worker->moveToThread(m_Thread);
    m_Thread->start();
    timer->start(5000);



void EntryPointClass::timeoutExpired()

    qDebug() << "timeout expired";
    if (m_Worker != NULL)
    
        QMetaObject::invokeMethod(m_Worker, "closeWorker", Qt::QueuedConnection);
    

// Worker.h

#ifndef WORKER_H
#define WORKER_H

#include <QtCore>

class Worker : public QObject

    Q_OBJECT
public:
    Worker();
    ~Worker();

public slots:
    void doSomething();
    void closeWorker();

private:
    bool m_bAbort;
    QMutex m_mutex;


signals:
    void finished();
;

#endif // WORKER_H

// Worker.cpp

#include "worker.h"
#include <unistd.h>
#include "QTcore"

Worker::Worker()
    : m_mutex()

    qDebug() << this->thread()->currentThreadId() << "Worker created";
    m_bAbort = false;
    //qDebug() << QString("Thread %1 - Worker created").arg("");//this->thread()->currentThreadId());


Worker::~Worker()

    qDebug() << this->thread()->currentThreadId() << "Worker destroyed";



void Worker::doSomething()

    while(!m_bAbort)
    
        sleep(2);
        qDebug() << this->thread()->currentThreadId() << "Do Something!";
    

    emit finished();


void Worker::closeWorker()

    qDebug() << this->thread()->currentThreadId() << "closeWorker triggered!";
    QMutexLocker mutexLocker(&m_mutex);
    m_bAbort = true;

【问题讨论】:

QtQueuedConnection 使方法在目标线程的事件循环中被调用。由于您停留在 while 循环 doSomething() 中,因此您的线程永远不会到达事件循环中的 close-worker 调用。您可以尝试调用processEvents() 或直接在源线程中调用closeWorker 方法。 为什么要使用invokeMethod,而不是把一个信号连接到槽然后发出这个信号? 【参考方案1】:

尝试发布自定义事件,而不是直接调用方法。这将要求您在处理您的自定义事件的目标上实现一个事件过滤器。只要目标线程中的事件循环处于活动状态,事件发布就始终有效。

也看看这个答案here。还有here。 希望这会有所帮助。

【讨论】:

你为什么要使用更复杂的方法来做同样的事情?

以上是关于QThread - 调用另一个线程的方法的主要内容,如果未能解决你的问题,请参考以下文章

QThread 通信线程安全

在 QThread::run 中间调用了一个插槽

[QThread]moveToThread()方法创建子线程只能用signal-slot来调用函数

QThread多线程编程经典案例分析(三种方法,解释了为什么使用moveToThread的根本原因,即为了避免调用QThread::exec() )

了解 qthread 子类的运行方法和线程上下文

QThread与多线程(比较清楚)