C++ QThread发出finished()信号,但isRunning()返回true,isFinished()返回false

C++ QThread发出finished()信号,但isRunning()返回true,isFinished()返回false,c++,qt,gps,blackberry-10,qthread,C++,Qt,Gps,Blackberry 10,Qthread,下面是我的qthread实现的代码。我正试图从卫星上获取gps数据。即使程序退出gpsSearch()slot函数,QThread也不会产生finished()信号。只要单击按钮,就会调用函数locateMe()。当线程第一次未启动并单击按钮时,它会为isRunning()函数打印真值,为isFinished()函数打印假值。我必须调用QTherad的quit()函数来手动停止线程。之后,它转到gnssProvider类中已连接的threadQuit()函数。但即使在这之后,如果我单击按钮,它也

下面是我的qthread实现的代码。我正试图从卫星上获取gps数据。即使程序退出
gpsSearch()
slot函数,QThread也不会产生finished()信号。只要单击按钮,就会调用函数
locateMe()
。当线程第一次未启动并单击按钮时,它会为
isRunning()
函数打印真值,为
isFinished()
函数打印假值。我必须调用QTherad的
quit()
函数来手动停止线程。之后,它转到
gnssProvider
类中已连接的
threadQuit()
函数。但即使在这之后,如果我单击按钮,它也会在
locateMe()
函数中为
isRunning
打印真值,为
isFinished()
打印假值

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

 }
GPSInfo::GPSInfo()
{
hybridGPSFound=satelliteGPSFound=networkGPSFound=false;
qDebug()退出();
}
void GPSInfo::LocateMe()
{

qDebug()QThread生命周期的工作方式如下:

  • 您可以调用
    QThread::start()
  • 此时,
    isRunning()
    应该开始返回true
  • 线程内部启动。它们发出
    started()
    信号
  • 线程内部调用
    run()
  • 除非在子类中重写它,
    run()
    调用
    exec()
  • exec()
    进入一个事件循环,并一直停留在那里,直到调用
    quit()
    exit()
  • exec()
    run()
    返回内部
  • 此时,
    isFinished()
    应该开始返回true和
    isRunning()
    false
  • 内部构件发出
    finished()
    信号
  • 内部构件进行一些最终清理
  • 线程真正终止
  • 因此,您需要在完成位置获取程序后调用
    quit()
    ,但是
    this->quit()
    没有在线程上调用
    quit()
    !这可能就是它没有做任何事情的原因

    您的代码看起来有点像是根据本文编写的:


    注意她是如何给她的工人一个
    finished()
    信号(与
    QThread::finished
    不同)并将其连接到
    QThread::quit()的
    slot.

    预期的行为是,线程在您手动终止它之前不会退出。正如塞巴斯蒂安所解释的,线程对象承载一个事件循环,因此直到事件循环退出它才会结束


    简而言之,您的信号插槽连接在概念上是向后的-对象应该在完成其任务时终止线程,而不是反过来终止线程。

    您使用哪种Qt版本

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

    您确定没有混淆isFinished和isRunning?您有
    “Thread Running:”
    在这两行中。不,我没有:)我太懒了,没法解决这个问题:你能发布完整的示例吗?也许线程没有完成。我会建议尝试将代码减少到一个最小的示例,编译后仍然显示问题。这将帮助你找出问题所在,并让我们提供答案(因为线程可能很棘手,准确地查看调用函数的位置/时间非常有用)。问题到底是什么?这篇文章是正确的答案。我只想补充一点,我们需要了解更多关于threadQuit槽的信息才能说得更多。如果该槽删除了线程,听起来您可能有一个悬空的指针。非常感谢,这让我更好地理解了QThread:)一个非常全面的答案,在别处很难找到。