2013-07-26 3 views
1

스레드에서 실행해야하는 클래스가 있으며 슬롯에 대한 이벤트 루프가 필요합니다. 현재는 moveToThread()으로 실행하지만, QThreadPool을 사용하고 싶습니다. 문제가 발생했습니다.QThreadPool 내에서 슬롯을 실행하십시오.

풀링 스레드 (나는 QThread::currentThread()과 함께이를 확인)에서 호출 QThreadPool 내 실행 가능한의 run() 방법으로 실행,하지만 내 슬롯은 풀 스레드에서 실행하지 않는, 그래서 객체가 이동되지 생각할 때 풀의 thread

슬롯이 정확히 QThreadmoveToThread() 메서드를 사용할 때 얻을 수있는 (올바른) 동작 인 수신기의 스레드에서 실행된다는 것을 알고 있기 때문에 이것을 생각합니다.

QRunnable (아래 예에서 Foo)을 풀링 된 스레드에서 완전히 실행하려면 어떻게해야합니까? 아니면 내가 잘못하고 있거나 잘못 이해 한 것입니까?

다음 POC는 문제를 보여줍니다

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

그러나 실제 코드에서는 네트워크에서 일부 데이터가 수신되기 때문에 신호가 즉시 방출되지 않습니다.

추 신 : POC는 here입니다.

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

당신의 연결 전화 이후

답변

1

어쩌면 당신은 두 가지로 class Foo에 로직을 분리 할 수있다.그런 다음 모든 신호를 작업자 개체로 전달합니다. 이제 슬롯은 풀링 된 스레드에서 호출됩니다.
그러나 QThreadPool은 너무 많은 동시 스레드를 만들지 않고 짧은 작업을 많이 실행하도록 설계되었습니다. 일부 작업은 대기열에 추가되고 다른 작업이 완료되기를 기다리고 있습니다. 이것이 의도가 아니라면, 좋은 이전 QThread으로 돌아가서 대신 사용할 수 있습니다.

+0

흥미 롭다. 나는 이것을 줄 것이다. – Paul

+0

+1, 문제가 해결 된 이후로 답을 표시했습니다. 실행 파일이 아니라 작업자에서 이벤트 루프를 실행 중이므로 정확하게 말한 것이 아닙니다. – Paul

0

은, 그것은 Qt는 :: Autoconnection 될 것입니다 연결 유형에 대한 기본 매개 변수를 사용했다. 신호가 풀링 된 스레드에서 방출되고 슬롯은 여전히 ​​foo에 속하며 foo는 주 스레드에 대한 스레드 연관 관계가 있습니다. 자동 연결은 슬롯을 메인 스레드의 이벤트 대기열에 넣기로 결정합니다.

당신이이 문제를 해결할 수있는 두 가지 방법이 있습니다 :

1.

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

와)합니다 (eventloop.exec 제거는; 실행 방법

2.

, 신호 슬롯을 연결하기 전에 현재 스레드에 푸 객체를 이동. QEventLoop
호스팅 서비스 공급자 QRunnable을, 당신은 QEventLoop::exec 메서드를 호출하기 전에 run()에서 작업자 스레드에서 생성 작업자 QObject :

+0

풀의 스레드에 대한 참조가 없기 때문에 두 번째 솔루션이 작동하지 않습니다. 어떤 스레드가 작업을 수행하도록 할당되는지 알 수 없습니다. 첫 번째 이벤트는 신호가 즉시 방출되지 않기 때문에 작동하지 않으며 이벤트 루프가 없기 때문에 run()이 반환 된 후 스레드가 종료됩니다. – Paul

+1

소유자 스레드에서만 "푸시"할 수 있기 때문에 개체를 현재 스레드로 이동할 수 없습니다. Qt :: DirectConnection을 사용하는 것은 나쁜 생각입니다. 이것은 슬롯이 작업자 스레드에서 호출되는 것을 보증하지 않습니다 (op가 예상 한 것처럼). – spiritwolfform

관련 문제