QThread 发出finished() 信号但isRunning() 返回true 并且isFinished() 返回false

2021-12-09 00:00:00 qt gps qthread c++ blackberry-10

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

Below is the code for my qthread implementation. I am trying to get gps data from satellite. QThread doesn't produce the finished() signal even when the programs exits gpsSearch() slot function. The function locateMe() is called whenever a button is clicked. The first time when the thread isnt started and the button is clicked it prints true value for isRunning() function and prints false value for isFinished() function. I had to call the quit() function of the QTherad to manually stop the thread. After that it goes to the connected threadQuit() function in the gnssProvider class. But even after that if I click the button it prints true value for isRunning and false for isFinished() in the locateMe() function.

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

 }

推荐答案

QThread 生命周期的工作方式是这样的:

The way the QThread lifecycle works is like this:

  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. 线程真正终止.
  1. You call QThread::start().
  2. At this point, isRunning() should start returning true.
  3. The thread internals start. They emit the started() signal.
  4. The thread internals call run().
  5. Unless you override this in a subclass, run() calls exec().
  6. exec() enters an event loop and stays there until quit() or exit() is called.
  7. exec() and run() return to the internals.
  8. At this point, isFinished() should start returning true and isRunning() false.
  9. The internals emit the finished() signal.
  10. The internals do some final cleanups.
  11. The thread terminates for real.

所以你需要在你的位置获取器完成后调用 quit() - 但是 this->quit() 没有调用 quit() 在线程上!这可能就是它什么都不做的原因.

So you need to call quit() after your location fetcher is done - but this->quit() isn't calling quit() on the thread! This is probably why it's not doing anything.

你的代码看起来有点像这篇文章之后的模式:

Your code looks a bit like it was patterned after this article:

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

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

Note how she gives her worker a finished() signal (not the same as QThread::finished) and connects it to the QThread::quit() slot.

相关文章