0

私は 2 つのスレッドを持つ Qt5 c++ アプリを持っています。メイン プログラムの起動時にスレッド A が開始されます。スレッド A の start メソッドが正常に実行されます。

ここまでは順調ですね。次に、メイン プログラムでスレッド A にシグナルを送信して QTimer を開始しますが、QTimer はそれを実行しますが、タイマーが期限切れになることはありません。

スレッド B は tcp 接続を処理します。アプリへの telnet 接続を開始すると、スレッド B が起動し、突然、スレッド A からの Qtimer が通常の間隔で期限切れになるのが見えます。

スレッド B が開始するまで、スレッド A の QTimer が期限切れにならないのはなぜですか?

スレッドがめちゃくちゃになっていると思います。製品の下のコードの最後のセクションに注意してください。

thread of this:  QThread(0x200fe00)  
thread of timer:  QThread(0x1fff470)

これは、ワーカー オブジェクト (これ) がタイマー オブジェクトとは別のスレッドにあることを示唆しています。このタイマー スレッド アドレスは、実際には MAIN スレッドです。なんで?よくわかりません。

提案?


私のメインアプリでは、次のようにスレッドを作成して開始します。

QThread * MyControllerThread = new QThread(this);

if (MyControllerThread) {

    TheController *worker = new TheController(MyControllerThread);

    if (worker) {
        connect(MyControllerThread, SIGNAL(started()), worker, SLOT(start()));
        connect(MyControllerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(MyControllerThread, SIGNAL(finished()), MyControllerThread, SLOT(deleteLater()));
        worker->moveToThread(MyControllerThread);  
        MyControllerThread->start();  
    } 

私のメインアプリでは、新しいスレッドにシグナルを送信します:

    emit sig_startlocalpeer(Types::EActionLocalServiceStart);  // Move the local peer to standby mode to start remote tests

私のスレッド(TheControllerオブジェクト)でスロットを実行します:

connect(&m_remotetestintervaltimer,SIGNAL(timeout()),this,SLOT(expiredRemoteTestIntervalTimer()));
m_remotetestintervaltimer.setTimerType(Qt::VeryCoarseTimer);
m_remotetestintervaltimer.start(REMOTETEST_TIMER_INTERVAL);  // Wait between ticks
qDebug() << "thread of this: " << this->thread();
qDebug() << "thread of timer: " << m_remotetestintervaltimer.thread();
4

2 に答える 2

1

これは Qt5 のバグではなく、Qt のスレッド精神の不正確な理解です。

Qt では、偶数ループを使用するスレッドと使用しないスレッドを実装する方法が 2 つあります。これはほんの小さな視覚的な例です。

イベントループなし

myMethodCalledInANewThread
{
    do{ ... }while(...);
}

イベントループあり

myMethodCalledInANewThread
{
    [...]
    exec();
}

(もちろん、do/while と偶数ループを混在させることはできますが、単純なままにしておきます)。

QTimer のドキュメントでは、以下を読むことができます。

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

したがって、2 番目のスレッドに 2 番目のイベント ループがないことは確かです。それが、説明した動作をする理由です。

Qt を使用してスレッドを完全に明確にするためのヒントをいくつか提供するには、以下をお読みになることをお勧めします。

QThread の実装がどのように多くのユーザーに誤解されているかについての非常に良い記事:

私はそれが役立つことを願っています;)

于 2014-08-10T09:53:48.860 に答える