10

以下は、私のqthread実装のコードです。衛星から GPS データを取得しようとしています。gpsSearch()プログラムがスロット関数を終了しても、QThread は finished() シグナルを生成しません。この関数locateMe()は、ボタンがクリックされるたびに呼び出されます。スレッドが開始されず、ボタンがクリックされたときに初めて、関数の真の値がisRunning()出力され、関数の偽の値が出力されisFinished()ます。quit()スレッドを手動で停止するには、QTheradの関数を呼び出す必要がありました。その後threadQuit()、クラス内の接続された関数に移動しgnssProviderます。しかし、その後でもボタンをクリックすると、関数に真の値と偽の値が出力されisRunningます。isFinished()locateMe()

GPSInfo::GPSInfo()
{
    hybridGPSFound = satelliteGPSFound = networkGPSFound = false;
    qDebug()<<"Thread Creating";
    gnssThread = new QThread;
    gnssProvider = new LocationFetcher(this,GEOLOCATION_PROVIDER_GNSS,1);
    gnssProvider->moveToThread(gnssThread);
    connect(gnssThread, SIGNAL(started()), gnssProvider, SLOT(gpsSearch()));
    connect(gnssThread, SIGNAL(finished()), gnssProvider, SLOT(threadQuit()));
}
void LocationFetcher::gpsSearch()
{
    if (BPS_SUCCESS != geolocation_request_events(0))
    {
       fprintf(stderr, "Error requesting geolocation events: %s", strerror(errno));
       return;
    }
    geolocation_set_provider(GPS_Search_Provider);
    geolocation_set_period(GPS_Search_Period);
    while (!stopThread)
    {
        bps_event_t *event = NULL;
        bps_get_event(&event, -1);

        if (event)
        {
            if (bps_event_get_domain(event) == geolocation_get_domain() && bps_event_get_code(event) == GEOLOCATION_INFO)
            {
                handle_geolocation_response(event);
                break;
            }
        }
    }
    geolocation_stop_events(0);

    this->quit();

}
void GPSInfo::LocateMe()
{
    qDebug()<<"Thread Running: "<<gnssThread->isFinished();
    qDebug()<<"Thread Running: "<<gnssThread->isRunning();

    gnssThread->start();
    hybridThread->start();
    networkThread->start();

 }
4

3 に答える 3

37

QThread ライフサイクルの仕組みは次のようになります。

  1. を呼び出しますQThread::start()
  2. この時点で、isRunning()true を返し始めるはずです。
  3. スレッド内部が開始します。それらは信号を発しstarted()ます。
  4. スレッド内部呼び出しrun().
  5. サブクラスでこれをオーバーライドしない限り、は をrun()呼び出しますexec()
  6. exec()イベント ループに入り、quit()またはexit()が呼び出されるまでそこにとどまります。
  7. exec()そしてrun()内部に戻ります。
  8. この時点で、 true とfalseisFinished()を返し始めるはずです。isRunning()
  9. 内部は信号を発しfinished()ます。
  10. 内部はいくつかの最終的なクリーンアップを行います。
  11. スレッドは実際に終了します。

quit()そのため、場所フェッチャーが完了した後に呼び出す必要がありますが、スレッドthis->quit()で呼び出しquit()ていません! これがおそらく何もしていない理由です。

コードは、この記事の後にパターン化されたように少し見えます。

http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

彼女がワーカーにfinished()信号 ( とは異なる) を与え、それをスロットQThread::finishedに接続する方法に注意してください。QThread::quit()

于 2013-06-13T18:26:28.417 に答える