我正在循环内调用一个函数:
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
我不知道为什么!谁能帮忙。
答案 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();
}