简体   繁体   English

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

[英]Stopping code execution for milliseconds at each iteration of loop

I'm calling a function inside a loop: 我在循环内调用一个函数:

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

The called function emits a signal and waits for 100 millisecond: 被调用的函数发出一个信号并等待100毫秒:

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

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

I have a slot which logs to console when receives a signal: 我有一个插槽,在接收到信号时会记录到控制台:

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

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

I expect the logs to be like this: 我希望日志是这样的:

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

But the actual log is like this: 但是实际的日志是这样的:

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

I cannot figure out why! 我不知道为什么! Can anybody help. 谁能帮忙。

singleShot adds a timer, then keeps executing. singleShot添加了一个计时器,然后继续执行。 When the time interval has passed, then your lambda will be called. 时间间隔过去后,您的lambda将被调用。 So you're starting three timers, and all three signals get received before the timeout of the first timer has passed. 因此,您要启动三个计时器,并且在第一个计时器的超时过去之前,所有三个信号都将被接收。

If you really need func to wait for 100ms use a sleep function. 如果您确实需要func等待100毫秒,请使用睡眠功能。

Let's analyze your code step by step: 让我们逐步分析您的代码:

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

Is equivalent to: 等效于:

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";
});
// ...

The following must be taken into account: 必须考虑以下几点:

  • In your case, the receiver and the sender begin same thread, so the slot is invoked immediately since Qt::AutoConnection is used by default. 在您的情况下,接收方和发送方开始同一线程,因此默认情况下使用Qt :: AutoConnection,因此立即调用该插槽。

  • The timers are launched when the synchronous part ends and at the indicated time 当同步部分结束并在指定的时间启动计时器

Considering the above and seeing that handleSignal consumes very little time your code is equivalent to: 考虑到上述情况,并看到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";

getting the behavior you get. 得到你得到的行为。

The same is what @1201ProgramAlarm indicates but using sleep is a bad option since it will block the event loop preventing other signals, events, etc run correctly, instead a possible option is to use QEventLoop: @ 1201ProgramAlarm指示的内容相同,但是使用sleep是一个不好的选择,因为它会阻止事件循环,从而阻止其他信号,事件等正确运行,而可能的选择是使用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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM