QThread - Call a method of another thread

I'm trying to call a method of another thread (not the Main), using invokeMethod. Unfortunately that makes the application crash as soon as it tries to execute the invokeMethod!

Am I mistaking something?

// 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();
}

// Entrypoint.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

// Entrypoint.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;
}

Answers


Instead of invoking a method directly, try posting a custom event. This will require that you implement an event filter at the target that handles your custom event. Event posting always works as long as an event loop is active in the target thread.

Take a look at this answer here too. Also here. Hope this helps.


Need Your Help

Storing Class object in an array

c++ arrays class object

Please take a look at the following:

How to go about composing core functions, rather then using imperative style?

performance clojure functional-programming lisp idiomatic

I have translated this code, the snippet below, from Python to Clojure. I replaced Python's while construct with Clojure's loop-recur here. But this doesn't look idiomatic.