2017-02-09 13 views
1

QThread内でQTimerを使用しようとしましたが、QTimertimeout()スロットに接続できませんでした。QTimerがタイムアウトスロットを呼び出さない

私は間違っていますか?ここで

が私のコードです:すべての

extern MainWindow *mainClass; 

class myObj : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit myObj(QObject *parent = 0); 
    ~myObj(); 
    QThread workerThread; 

    int percent; 
    QTimer *percentTimer; 

public slots: 
    void doWork(); 
    void percentUpdate(); 
    void startFunction(); 

signals: 
    void start(); 
    void UpdateResult(); 
}; 

myObj::myObj(QObject *parent) : QObject(parent) 
{ 
    moveToThread(&workerThread); 

    connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater())); 
    connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult())); 
    connect(&workerThread, SIGNAL(started()), this, SLOT(doWork())); 
    connect(this, SIGNAL(start()), this, SLOT(startFunction())); 

    percent++; 
    percentTimer = new QTimer(); 
    percentTimer->moveToThread(&workerThread); 
    percentTimer->setInterval(1000); 
    connect(percentTimer, SIGNAL(timeout()), this,SLOT(percentUpdate())); 

} 

myObj::~myObj() { 
    workerThread.quit(); 
    workerThread.wait(); 
    if (percentTimer) percentTimer->deleteLater(); 
} 

void myObj::doWork() 
{ 
    emit start(); 
    workerThread.exec();  
} 

void myObj::startFunction() 
{ 
    percentTimer->start(); 
    QThread::sleep(60); 
    percentTimer->stop();  
} 

void myObj::percentUpdate() 
{ 
    qDebug() << "In Timer" << percent++; 
    emit UpdateResult(); 

} 
+0

これをデバッガで実行するとどうなりますか?まず、各メソッドにブレークポイントを設定します。どちらが呼び出され、どのような順序で? – MrEricSir

+0

スロットpercentUpdateを除いてすべてがうまくいきますタイムアウト@MrEricSir –

+0

@MrEricSir、 'percentTimer-> moveToThread(;);の前に' connect(percentTimer ...) 'を移動しようとしました –

答えて

1

まず、あなたはその文脈でmyObj仕事をできるようにworkerThreadをshartなければならない可能性がstart信号に接続されているスロットはならないので(後が必要な接続を作成し、それを開始そうでなければ実行される)。 代わりに、あなたはこのようなものを使用する必要がありQThread::sleepFor使用する:QThread::sleepForは全体のスレッドの実行を凍結しているため、遅延を作成するために

QEventLoop loop; 
QTimer::singleShot(60000, &loop, SLOT(exit())); 
loop.exec(); 

を。したがって、このスレッドにバインドされたイベントは処理されません。

workerThread.exec()ここでは役に立たない。

+0

ありがとうthat works(y)@RealFresh –

4

これは、作成したスレッドとは別のスレッドからQTimerを起動しようとしているためです。 QTimerとスレッドを使用する場合は、QTimerを制御するスレッドにQTimerを作成することに非常に注意する必要があります。 QTimer class documentationから

:マルチスレッド・アプリケーションで

、あなたはイベントループを持っている任意のスレッドでQTimerを使用することができます。非GUIスレッドからイベントループを開始するには、QThread :: exec()を使用します。 Qtはタイマーのスレッドアフィニティを使用して、どのスレッドがtimeout()シグナルを送出するかを決定します。このため、のスレッドは、そのスレッドでタイマを起動および停止する必要があります。;別のスレッドからタイマーを開始することはできません。あなたのケースpercentTimer = new QTimer();

あなたdoWorkstart信号がworkerThreadから放出される一方で、メインスレッド、(あなたが前にmoveToThread使用していても、これはまだそれを実行して、メインスレッドである)から実行されます。

あなたは、例えば QTimerが適切なスレッドによって作成され、所有されていることを保証するために、むしろ、コンストラクタよりも、あなたの workerThreadから呼び出さ void init()スロットからあなた new QTimerを行うことができます

myObj::myObj(QObject *parent) : QObject(parent), percentTimer(nullptr) 
{ 
    moveToThread(&workerThread); 

    connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater())); 
    connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult())); 
    connect(&workerThread, SIGNAL(started()), this, SLOT(init())); 
    connect(&workerThread, SIGNAL(started()), this, SLOT(doWork())); 
    connect(this, SIGNAL(start()), this, SLOT(startFunction())); 

    percent++; 
} 

void myObj::init() { 
    percentTimer = new QTimer(); 
    percentTimer->setInterval(1000); 
    connect(percentTimer, SIGNAL(timeout()), this, SLOT(percentUpdate())); 
} 
関連する問題