Как запустить его в другом потоке Qt?

#c #multithreading #qt #qt5 #qthread

Вопрос:

Имея в виду Qthread, я попробовал следующее, но, похоже, все по-прежнему работает в том же потоке.

main.cpp

 #include "widget.h"

#include <QApplication>

#include "core.h"

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

    qDebug() << Q_FUNC_INFO << QThread::currentThreadId();

    Core core;

    Widget w(core);
    w.show();

    return a.exec();
}
 

функция.h

 #ifndef FUNC_H
#define FUNC_H

#include <QDebug>
#include <QThread>

class Func : public QObject
{
    Q_OBJECT
public:
    explicit Func()
    {
        qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
    }

    void compute()
    {
        qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
    }
};

#endif // FUNC_H
 

ядро.h

 #ifndef CORE_H
#define CORE_H

#include <QObject>

#include "func.h"

class Core : public QObject
{
    Q_OBJECT

    QThread thread;
    Func* func = nullptr;

public:
    explicit Core(QObject *parent = nullptr)
    {
        func = new Func();
        func->moveToThread(amp;thread);
        connect(amp;thread, amp;QThread::finished, func, amp;QObject::deleteLater);
        thread.start();
    }

    ~Core() {
        thread.quit();
        thread.wait();
    }

public slots:
    void compute(){func->compute();}

signals:

};

#endif // CORE_H
 

виджет.h

 #ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include "core.h"

class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(Coreamp; core)
    {
        qDebug() << Q_FUNC_INFO << QThread::currentThreadId();

        core.compute(); // This should run on a different thread ?
    }

};

#endif // WIDGET_H
 

Запустив, я получаю результат:

 int main(int, char **) 0x107567e00
Func::Func() 0x107567e00
Widget::Widget(Core amp;) 0x107567e00
void Func::compute() 0x107567e00
 

Выше вывод был из macOS, но в Windows я получил аналогичный результат.

Так что же я делаю не так?

Ответ №1:

Вы не можете вызвать слот compute() напрямую, он вызовет его в том же потоке, в котором выполняется вызвавший его код (как вы можете видеть на выходе).

Вам нужно запустить слот с помощью механизма сигналов/слотов (или с invokeMethod() помощью , но давайте проигнорируем это).

Обычно это делается путем подключения started() сигнала потока к слоту, а затем вызова QThread::start() из основного потока. Это приведет к тому, что слот будет вызван во вторичном потоке сразу после запуска потока.

Комментарии:

1. Понял! И было бы интересно получить предупреждение, когда вызовы методов для этого объекта не выполняются косвенно. Есть какие-нибудь предложения по этому аспекту? В идеале я хотел бы гарантировать, что вызовы методов этого объекта выполняются в другом потоке (только).