QThread: вызовите сигнал в правильном потоке

У меня есть несколько очень трудоемких задач для выполнения в приложении с графическим интерфейсом, и я хочу, чтобы они были многопоточными, чтобы он не зависал в моем графическом интерфейсе.

Для этого я создал тему и запустил таймер. Я подключил метод timeout() из моего таймера к функции, отнимающей время, которую я хочу распараллелить, в методе «запуска» моего потока, но когда вызывается сигнал, вместо этого в основном потоке вызывается функция, отнимающая время. того, что я создал.

Вот мой код, упрощенный для примера:

void MyThread::run()
{
   m_pTimer = new QTimer()
   connect(m_pTimer, SIGNAL(timeout()), this, SLOT(timeConsumingMethod()));
   m_pTimer->start(x);
}

Я напечатал значение статического метода QThread::currentThread() в "timeConsumingMethod", в MyThread::run() и в моем основном, и его значение такое же, как и в моем основном.

Как я могу запустить свою функцию в отдельном потоке? И что еще более важно, почему мой код неверен?


person lagarkane    schedule 19.04.2013    source источник
comment
Несмотря на то, что спрашивающий отметил, что на вопрос дан ответ в дубликате (так близко), это не совсем то же самое. Описанная проблема заключается в том, что соединение использует Qt::Autoconnection, а QThread this имеет сходство потока с основным потоком (у него никогда нет сходства потока с потоком, которым он управляет), поэтому сигнал ставится в очередь, а слот вызывается основным потоком. цикл событий потока. Таким образом, решение действительно состоит в том, чтобы переместить timeConsumingMethod() в другое QObject и создать экземпляр с тем же сходством потоков, что и таймер.   -  person hyde    schedule 04.03.2014


Ответы (1)


"Ты делаешь это неправильно." :)

попробуй это:

мой рабочий.ч

#include ...

class MyWorker : public QObject {
   Q_OBJECT
public:
   explicit MyWorker(QObject* parent = 0);
public slots:
   void timeConsumingMethod();
}

мой рабочий.cpp

#include "myworker.h"

#include ...

MyWorker::MyWorker(QObject* parent) : 
   QObject(parent) 
{
   /*
   ...
   */
}

void MyWorker::timeConsumingMethod() {
   /*
   ...
   */
}

код

/*...*/
MyWorker* worker = new MyWorker();
QThread* workerThread = new QThread();
QTimer* timer = new QTimer();


worker->moveToThread(workerThread);
worker->connect(timer, SIGNAL(timeout()), SLOT(timeConsumingMethod()));

// don't forget proper obj deletion
// not the best way, but...
worker->connect(workerThread, SIGNAL(destroyed()), SLOT(deleteLater());

workerThread->start();
timer->start(x);

в этом случае worker будет «жить» в workerThread. Механизм QT SIGNAL-SLOT поддерживает соединение между объектами в разных потоках.

этот подход намного лучше, чем «процедурный способ», путем повторной реализации метода run() и наследования QThread

worker работает, QThread управляет потоком

источник: http://qt-project.org/wiki/Threads_Events_QObjects

person sanperrier    schedule 19.04.2013