在每次循环迭代时停止执行代码数毫秒

时间:2019-09-03 05:07:41

标签: c++ qt

我正在循环内调用一个函数:

for (Item *item : *items) {
    item->func();
}

被调用函数发出信号并等待100毫秒:

void Item::func()
{
    // Emit a signal
    emit castSignal();

    QTimer::singleShot(100 /* msec */, [](){
        qDebug() << "Wait for 100 milliseconds";
    });
}

我有一个插槽,可在接收到信号时登录控制台:

QObject::connect(this, &Item::castSignal, this, &Item::handleSignal);

void Item::handleSignal()
{
    qDebug() << "Signal received";
}

我希望日志如下:

Signal received
Wait for 100 milliseconds
Signal received
Wait for 100 milliseconds
Signal received
Wait for 100 milliseconds

但是实际的日志是这样的:

Signal received
Signal received
Signal received
Wait for 100 milliseconds
Wait for 100 milliseconds
Wait for 100 milliseconds

我不知道为什么!谁能帮忙。

2 个答案:

答案 0 :(得分:3)

singleShot添加一个计时器,然后继续执行。时间间隔过去后,您的lambda将被调用。因此,您要启动三个计时器,并且在第一个计时器的超时过去之前,所有三个信号都将被接收。

如果您真的需要func等待100毫秒,请使用睡眠功能。

答案 1 :(得分:2)

让我们逐步分析您的代码:

for (Item *item : *items) {
    item->func();
}

等效于:

emit castSignal();
QTimer::singleShot(100 /* msec */, [](){
    qDebug() << "Wait for 100 milliseconds";
});
emit castSignal();
QTimer::singleShot(100 /* msec */, [](){
    qDebug() << "Wait for 100 milliseconds";
});
emit castSignal();
QTimer::singleShot(100 /* msec */, [](){
    qDebug() << "Wait for 100 milliseconds";
});
// ...

必须考虑以下因素:

  • 在您的情况下,接收方和发送方开始相同的线程,因此默认情况下使用Qt :: AutoConnection,因此立即调用该插槽。

  • 当同步部分结束并在指定的时间启动计时器

考虑到上述情况,发现handleSignal消耗的时间很少,相当于:

qDebug() << "Signal received";
qDebug() << "Signal received";
qDebug() << "Signal received";

T: 100 ms

qDebug() << "Wait for 100 milliseconds";
qDebug() << "Wait for 100 milliseconds";
qDebug() << "Wait for 100 milliseconds";

了解自己的行为。

@1201ProgramAlarm所指示的相同,但是使用睡眠是一个糟糕的选择,因为它会阻止事件循环,从而阻止其他信号,事件等正确运行,相反,可能的选择是使用QEventLoop:

void Item::func()
{
    // Emit a signal
    emit castSignal();
    QEventLoop loop;

    QTimer::singleShot(100 /* msec */, [&loop](){
        qDebug() << "Wait for 100 milliseconds";
        loop.quit();
    });
    loop.exec();
}