2012-11-17 3 views
0

여러 스레드가 특정 시점에 시작되도록 보장하는 Qt 용 장벽 유사 동기화 프리미티브를 작성하려고합니다. 그러나 나는 신호 (예 : started())가 작동하지 않는 상황에 처해있는 것처럼 보입니다.여러 스레드가 시작될 때까지 대기 중 (시작되지 않음)

최소한의 (비) 작동 예제를 컴파일하기 위해 코드를 축소하려고했습니다.

======== 
main.cpp 
======== 
#include <QtCore> 
#include <QCoreApplication> 

#include "qmultithreadwaiter.hpp" 
#include <QSignalMapper> 
#include <qdebug.h> 

#define dlog qDebug() 

class Test: public QThread { 

public: 
    virtual void run() { 
     QThread::sleep(500); 
    } 
}; 

int main(int argc, char *argv[ ]) { 
    QCoreApplication a(argc, argv); 
    Test t1, t2; 
    QMultiThreadWaiter w; 
    w.addThread(1, &t1); 
    w.addThread(2, &t2); 

    t1.start(); 
    t2.start(); 

    w.wait4all(); 
    dlog << "Wait completed"; 

    return 0; 
} 

========================= 
qmultithreadwaiter.hpp 
=========================  
// Qt includes 
#include <QSignalMapper> 
#include <QMap> 
#include <QThread> 

class QMultiThreadWaiter: public QThread { 
Q_OBJECT 

    QMap < int, bool > started; 
    QSignalMapper sm; 

private slots: 
    void threadStarted(int id); 
    void someThreadStarted(); 

signals: 
    void allStarted(); 

public: 
    QMultiThreadWaiter(); 

    void addThread(int id, QThread* t); 
    void wait4all(); 

}; 
================= 
qmultithreadwaiter.cpp 
================= 
#include "qmultithreadwaiter.hpp" 

// Qt includes 
#include <QThread> 
// Debug includes 
#include <qdebug.h> 

#define dlog qDebug() 

// Project includes 

void QMultiThreadWaiter::threadStarted(int id) { 
    dlog << "Thread #" << id << " started!"; 
    started[ id ] = true; 
    QMapIterator < int, bool > mi(started); 
    while (mi.hasNext()) { 
     mi.next(); 
     if (!mi.value()) 
     return; 
    } 

    dlog << "All threads started!"; 

    // All threads are started 
    emit allStarted(); 
} 

void QMultiThreadWaiter::addThread(int id, QThread* t) { 
    dlog << "Adding thread " << t << " with id " << id; 
    sm.setMapping(t, id); 
    connect(t, SIGNAL(started()), &sm, SLOT(map()), Qt::QueuedConnection); 
    connect(t, SIGNAL(started()), this, SLOT(someThreadStarted()), 
      Qt::QueuedConnection); 
} 
void QMultiThreadWaiter::wait4all() { 
    dlog << "Starting this thread"; 
    start(); 
    dlog << "Going to wait"; 
    wait(); 
    dlog << "Wait finished"; 
} 

QMultiThreadWaiter::QMultiThreadWaiter() { 
    sm.moveToThread(this); 
    connect(&sm, SIGNAL(mapped(int)), this, SLOT(threadStarted(int)), 
      Qt::QueuedConnection); 
    connect(this, SIGNAL(allStarted()), this, SLOT(quit()), 
      Qt::QueuedConnection); 
    connect(this, SIGNAL(started()), this, SLOT(someThreadStarted()), 
      Qt::QueuedConnection); 
} 

void QMultiThreadWaiter::someThreadStarted() { 
    dlog << "Some thread started!"; 
} 

출력 :

Adding thread QThread(0x28fefc) with id 1 
Adding thread QThread(0x28fef4) with id 2 
Starting this thread 
Going to wait 
<stuck> 

어떤 이상한 것은 심지어 someThreadStarted()this 요구되지 않는다는 점이다. 제발, 조언 해.

+0

내가 'started()'신호는 스레드 내부에서 eventloop을 사용할 때만 emmited라고 생각합니다. 그렇지 않으면 그것을 emmited되지 않습니다. run 메소드에'exec()'를 넣고 신호가 emmited인지 확인하십시오. –

답변

0

스레드에 실행중인 이벤트 루프가 없습니다. main()에서 w.wait4all();으로 전화하면 실행이 wait()에 도달하면 주 스레드가 차단됩니다. Qt::QueuedConnection을 사용하여 신호를 연결하면 대상 스레드의 컨트롤이 이벤트 루프로 돌아갈 때 슬롯이 호출된다는 것을 의미합니다. 이는 테스트 스레드를위한 것이 아닙니다. 한편, 주 스레드는 wait()에서 차단되며 이벤트 루프가 없습니다 (QCoreApplication::exec()는 호출되지 않습니다). 주 스레드는 또한 수신 대기열에있는 신호를 처리 할 수 ​​없으므로 this 스레드도 started()을 방출하지 않는 것입니다.

관련 문제