首页 > 解决方案 > 一个关于 QTimer::singleShot 的奇怪问题

问题描述

我写了一个调用 QTimer::singleShot 的函数来确保它不应该超时。但我得到了一个奇怪的结果。

int Test(int x)
{
    QEventLoop loop;

    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [&](){
        loop.exit(x);
    });
    timer.start(7000);

    QTimer::singleShot(10000, std::bind(&QEventLoop::exit, &loop, 3));

    return loop.exec();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    qDebug() << Test(1) << endl;
    qDebug() << Test(2) << endl;

    return a.exec();
}

我希望输出为 1 2 但实际输出为 1 3

标签: qt

解决方案


看起来像未定义的行为。关于为什么您可能会看到所描述的症状,请考虑您的实施Test......

int Test(int x)
{
    QEventLoop loop;

    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [&](){
        loop.exit(x);
    });
    timer.start(7000);

    QTimer::singleShot(10000, std::bind(&QEventLoop::exit, &loop, 3));

    return loop.exec();
}

您构建一个本地QEventLoop. 然后,您设置了两个都退出本地事件循环的计时器回调(7 秒和 10 秒之后) 。第一次超时将退出导致Test完成并返回的循环。但是仍然有一个超时未决,它也将尝试退出 now invalid QEventLoop。当您Test再次调用时,Test(2)很有可能QEventLoop在与上一次调用相同的地址构造新的Test。最终结果是QEventLoop仍然挂起的超时使用的地址变为“有效”。因此,您看到的两个值实际上来自调用Test(1).

正如我在一开始所说的那样——未定义的行为。


推荐阅读