【问题标题】:QThread::sleep not work correctly when system time is changed更改系统时间时 QThread::sleep 无法正常工作
【发布时间】:2018-04-26 09:27:07
【问题描述】:

请帮我解决这个问题。

我创建的一个QT 应用程序有一个QThread。在 run 函数中,在 while(1) 循环中使用 QThread::sleep。我在调用睡眠之前放置了 qDebug。当我运行程序时。 “睡眠”日志将每 1 秒打印一次。 之后,我通过命令 timedatectl set-time '2015-11-23 08:10:40' 更改系统时间。 现在,“睡眠”日志不再打印出来了!

void TestThread::run()
{
    while (1) {
        qDebug() << "sleep";
        sleep(1);
    }
}

感谢您的帮助!

【问题讨论】:

  • 这听起来令人惊讶。出于好奇:如果将时间设置回今天(设置为过去之后),线程会再次打印吗?
  • 是的!它再次打印。太令人惊讶了!
  • fwiw,不同的库,类似的问题:svn.boost.org/trac10/ticket/6787
  • 我记得 Glib 提供了 sleep_for()sleep_until()。其中一个在 Windows 中引起了麻烦(不幸的是,我忘记了其中的哪一个)。可能是,您的系统的实现已损坏。你的操作系统是什么?
  • 可能,在您的特定操作系统上更深入地研究nanosleep() 可能是值得的。 (我不得不承认我在 Windows 上开发了很多年(尽管我尝试编写可移植代码)。在我使用 Linux 和 Irix 之前,但那是很久以前的事了......)

标签: c++ qt


【解决方案1】:

查了源码,发现QThread::sleep有实现:

void QThread::sleep(unsigned long secs)
{
    struct timeval tv;
    gettimeofday(&tv, 0);
    struct timespec ti;
    ti.tv_sec = tv.tv_sec + secs;
    ti.tv_nsec = (tv.tv_usec * 1000);
    thread_sleep(&ti);
}

static void thread_sleep(struct timespec *ti)
{
    pthread_mutex_t mtx;
    pthread_cond_t cnd;

    pthread_mutex_init(&mtx, 0);
    pthread_cond_init(&cnd, 0);

    pthread_mutex_lock(&mtx);
    (void) pthread_cond_timedwait(&cnd, &mtx, ti);
    pthread_mutex_unlock(&mtx);

    pthread_cond_destroy(&cnd);
    pthread_mutex_destroy(&mtx);
}

关注这个帖子https://linux.die.net/man/3/pthread_cond_timedwait。如果支持时钟选择选项,则条件变量应具有时钟属性,该属性指定用于测量 abstime 参数指定的时间的时钟。当此类超时发生时,pthread_cond_timedwait() 仍应释放并重新获取 mutex 引用的 mutex。 pthread_cond_timedwait() 函数也是一个取消点。

因此,如果我将系统更改为 pass,睡眠功能将一直睡眠直到满足 >= 系统时间开始睡眠 + 睡眠时间。

【讨论】:

    【解决方案2】:

    根据您的经验,QThread::sleep 没有针对某个稳定的时钟实现,因此时间倒退不会像您预期的那样工作。

    所以,问题是:你想要什么?一种抗时间变化的睡眠功能? 然后在派生的 QThread 类中实现自己的一些函数,它将当前时间点保存为http://en.cppreference.com/w/cpp/chrono/steady_clock,然后对其进行检查。如果自上次调用以来已经过去了足够多的秒数。当然,这是主动等待,应该通过传递控制而不是进行另一个循环来细化。

    【讨论】:

    • 另外一个提示:我刚刚看到void QThread::yieldCurrentThread(),正好可以用来交出控制权。
    • 感谢您的回答。在我的项目中,我想创建一个线程,每 900 毫秒选通一次看门狗(看门狗定时器设置为 1 秒)。用户可以更改系统时间。并且系统将重新启动,因为线程如上所述挂起。我通过在 unistd.h 中使用睡眠功能来解决问题,它工作正常。但是,我的老板需要解释为什么 QThread::sleep 不起作用。
    猜你喜欢
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 2017-10-27
    • 2014-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多