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. 此时,isFinished()应该开始返回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 回答
1

在您手动终止它之前,线程不会退出是预期的行为。线程对象承载了一个事件循环,因此在事件循环退出之前它不会完成,正如 Sebastian 解释的那样。

简而言之,您的信号槽连接在概念上是向后的 - 对象应该在完成它的事情时终止线程,而不是相反。

于 2013-06-17T18:07:40.563 回答
0

您使用哪个 Qt 版本?

Qt 4.8 在 4.8.4 之前返回错误值(Qt bug 30251)。此错误已在 4.8.5 中修复。

于 2017-04-19T14:04:50.437 回答