2013-06-11 12 views
9

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

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(); 

} 
+3

isFinishedとisRunningが混在していないことは確かですか?両方の行に '' Thread Running: ''があります。 –

+0

いいえ私はそれを修正するにはあまりにも怠惰でした:) P – Tahlil

+1

あなたは完全な例を投稿できますか?多分スレッドは終了しませんでした –

答えて

27

QThreadのライフサイクルが機能する方法は、このようなものです:

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

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

あなたのコードでは、それのようなビットは、この記事の後にパターン化されたになります。彼女は彼女の労働者finished()信号(QThread::finishedと同じではない)を与え、QThread::quit()スロットに接続する方法

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

注意。

+0

この投稿は正しい答えです。私はもっ​​と多くのことを言うにはthreadQuitスロットについてもっと知る必要があると付け加えます。そのスロットがスレッドを削除した場合、ぶら下がっているポインタがあるかもしれないような私に聞こえます。 – Phlucious

+0

ありがとうQThreadについてのより良い理解を与える多くをありがとう:) – Tahlil

+0

非常に包括的な答えは、他の場所で見つけることは困難です。 – Trilarion

1

スレッドを手動で終了するまで、スレッドが終了しないようにすることを想定しています。スレッドオブジェクトはイベントループをホストします。したがって、Sebastianは説明したように、イベントループが終了するまで終了しません。

要するに、信号スロットの接続は、概念的に後ろ向きです。オブジェクトは、スレッドの処理が終了したときにスレッドを終了する必要があります。

0

どのQtバージョンをお使いですか?

4.8.4までQt 4.8が間違った値を返しました(Qt bug 30251)。 このバグは4.8.5で修正されています。

関連する問題