15

特定のスレッドで QTimer を開始しようとしています。ただし、タイマーは実行されていないようで、何も印刷されていません。タイマー、スロット、またはスレッドと関係がありますか?

main.cpp

    #include "MyThread.h"
    #include <iostream>
    using namespace std;

    int main(int argc, char *argv[]) {
        MyThread t;
        t.start();
        while(1);
    }

MyThread.h

    #ifndef MYTHREAD_H
    #define MYTHREAD_H

    #include <QTimer>
    #include <QThread>
    #include <iostream>

    class MyThread : public QThread {
        Q_OBJECT
    public:
        MyThread();
    public slots:
        void doIt();
    protected:
        void run();
    };

    #endif  /* MYTHREAD_H */

MyThread.cpp

    #include "MyThread.h"

    using namespace std;

    MyThread::MyThread() {
        moveToThread(this);
    }

    void MyThread::run() {
        QTimer* timer = new QTimer(this);
        timer->setInterval(1);
        timer->connect(timer, SIGNAL(timeout()), this, SLOT(doIt()));
        timer->start();
    }

    void MyThread::doIt(){
        cout << "it works";
    }
4

6 に答える 6

28

私がコメントしたように(リンクの詳細情報)、あなたは間違っています:

  1. スレッド データを保持するオブジェクトを別のオブジェクト ( の責任者doIt()) と混合しています。それらは分離する必要があります。
  2. あなたの場合、サブクラス化する必要はありませんQThreadrunさらに悪いことに、メソッドが何をしていたかを考慮せずにメソッドをオーバーライドしています。

コードのこの部分で十分です

QThread* somethread = new QThread(this);
QTimer* timer = new QTimer(0); //parent must be null
timer->setInterval(1);
timer->moveToThread(somethread);
//connect what you want
somethread->start();

現在 (Qt バージョン >= 4.7) では、デフォルトでメソッドQThread内でイベント ループが開始されます。run()スレッド内で実行するには、オブジェクトを移動するだけです。ドキュメントを読む...

于 2012-05-08T06:14:51.493 に答える
9

AQTimerは、イベント ループを持つスレッドでのみ機能します。

http://qt-project.org/doc/qt-4.8/QTimer.html

マルチスレッド アプリケーションでは、イベント ループを持つ任意のスレッドで QTimer を使用できます。非 GUI スレッドからイベント ループを開始するには、QThread::exec() を使用します。Qt は、タイマーのスレッド アフィニティを使用して、どのスレッドが timeout() シグナルを発行するかを決定します。このため、スレッド内でタイマーを開始および停止する必要があります。別のスレッドからタイマーを開始することはできません。

于 2012-05-08T04:19:02.847 に答える
1

タイマーを使用するには、イベント ループが必要です。私のコードで同じ問題を解決した方法は次のとおりです。

MyThread::MyThread() {
}

void MyThread::run() {
    QTimer* timer = new QTimer(this);
    timer->setInterval(1);
    timer->connect(timer, SIGNAL(timeout()), this, SLOT(doIt()));
    timer->start();

    /* Here: */
    exec();             // Starts Qt event loop and stays there
   // Which means you can't have a while(true) loop inside doIt()
   // which instead will get called every 1 ms by your init code above.
}

void MyThread::doIt(){
    cout << "it works";
}

他のポスターが言及していないドキュメントの関連部分は次のとおりです。

int QCoreApplication::exec()

メイン イベント ループに入り、exit() が呼び出されるまで待機します。exit() に設定された値を返します (exit() が quit() 経由で呼び出された場合は 0)。イベント処理を開始するには、この関数を呼び出す必要があります。メイン イベント ループは、ウィンドウ システムからイベントを受け取り、アプリケーション ウィジェットにディスパッチします。アプリケーションがアイドル処理を実行する (つまり、保留中のイベントがない場合は常に特別な関数を実行する) ようにするには、QTimer を 0 タイムアウトで使用します。processEvents() を使用すると、より高度なアイドル処理スキームを実現できます。

于 2017-10-16T20:06:53.273 に答える