2013-07-26 2 views
1

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

При запуске с QThreadPoolrun() метода моего работоспособного вызывается из объединенного потока (проверить это с QThread::currentThread()), но мои слоты не работают в объединенном потоке, так что я думаю, что объект не перемещаются поток в пуле.

Я думаю, это потому, что я знаю, что слоты запускаются в потоке получателя, что является точно (правильным) поведением, которое я получаю при использовании метода и QThread.

Как получить мой QRunnable (Foo в примере ниже), который будет полностью запущен в пул потоков? Или это что-то я делаю неправильно или неправильно понял?

В следующем РОС демонстрирует проблему:

foo.h

#ifndef FOO_H 
#define FOO_H 

#include <QObject> 
#include <QRunnable> 
#include <QEventLoop> 

class Foo : public QObject, public QRunnable 
{ 
    Q_OBJECT 
public: 
    explicit Foo(int data, QObject *parent = 0); 
    void run(); 
signals: 
    void startWorking(); 
public slots: 
    void doWork(); 

private: 
    QEventLoop eventLoop; 
    int data; 
}; 

#endif // FOO_H 

foo.cpp

#include "foo.h" 

#include <QThread> 
#include <QDebug> 

Foo::Foo(int d, QObject *parent) : 
    QObject(parent), eventLoop(this), data(d) 
{ 
} 

void Foo::run() 
{ 
    qDebug() << "run() in: " << QThread::currentThread(); 
    connect(this, SIGNAL(startWorking()), this, SLOT(doWork())); 
    emit startWorking(); 
    eventLoop.exec(); 
} 

void Foo::doWork() 
{ 
    qDebug() << "doWork() in: " << QThread::currentThread(); 
} 

main.cpp

#include <QCoreApplication> 
#include <QThreadPool> 

#include "foo.h" 

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

    Foo *foo = new Foo(42); 

    QThreadPool::globalInstance()->start(foo); 

    return a.exec(); 
} 

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

PS: POC также можно найти here.

ответ

1

Может быть, вы могли бы разделить свою логику в class Foo на два:
хостер QRunnable с QEventLoop, и работник QObject, который вы создаете на рабочем потоке в run() перед вызовом метода QEventLoop::exec.Затем вы пересылаете все сигналы рабочему объекту. Итак, теперь ваши слоты будут вызываться в объединенной нити.
Однако QThreadPool предназначен для выполнения множества коротких задач без создания слишком большого количества одновременных потоков. Некоторые задачи выставляются в очередь и ждут, когда другие закончатся. Если это не ваше намерение, вы можете вернуться к добрым старым QThread и использовать его вместо этого.

+0

Интересно, я дам этот снимок. – Paul

+0

+1, отмеченный как ответ, так как я решил проблему, не так, как вы сказали, потому что я запускаю цикл событий в рабочем, а не в runnable. – Paul

0

С вашего подключения вызова

connect(this, SIGNAL(startWorking()), this, SLOT(doWork())); 

используется параметр по умолчанию для типа подключения, это будет Qt :: AutoConnection. Сигнал испускается из объединенной нити, а слот все еще принадлежит foo, который имеет сродство нити к основному потоку. Автосоединение решит разместить слот в очереди событий основного потока.

Есть два способа исправить это:

1.

connect(this, SIGNAL(startWorking()), this, SLOT(doWork()), Qt::DirectConnection); 

и снимите eventloop.exec();

2.

в методе выполнения, переместить объект Foo к текущему потоку перед подключением сигнала и слота.

+0

Второе решение не будет работать, так как у меня нет ссылки на поток в пуле, я не знаю, какой поток будет назначен для выполнения работы. Первый не будет работать, так как сигнал сразу не будет испускаться, и поскольку у меня нет цикла событий, поток выйдет после возврата функции run(). – Paul

+1

вы не можете переместить объект в текущий поток, потому что вы можете только «нажать» из потока владельца. Использование Qt :: DirectConnection - также плохая идея, так как это не гарантирует, что слоты будут вызваны в рабочий поток (как кажется, кажется, op) – spiritwolfform

Смежные вопросы