QTimer::singleShot 仅在间隔为 0 时调用 lambda
Posted
技术标签:
【中文标题】QTimer::singleShot 仅在间隔为 0 时调用 lambda【英文标题】:QTimer::singleShot only calling lambda when interval is 0 【发布时间】:2017-08-24 14:27:49 【问题描述】:注意:我的原始帖子有一个重要的遗漏:我遗漏了我已经在 main 开头实例化了主 QApplication
实例。创建两个QApplication
实例是导致问题的原因。使用相同的 QApplication
实例而不是创建两个解决了该问题。
我的意图是在主应用程序之前运行QApplication
以迭代可用的蓝牙设备,以找到特定的设备。如果在某个时间限制内没有找到特定的,则终止QApplication
。第一个存储的 lambda (startDiscovery
) 在调用 QApplication::exec()
后立即被调用,但第二个存储的 lambda (cancelDiscovery
) 永远不会被调用!相关部分如下:
#include <QtBluetooth/QBluetoothDeviceInfo>
#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
#include <QtBluetooth/QBluetoothLocalDevice>
#include <QTimer>
#include <QString>
#include <QApplication>
#include <memory>
#define TARGET_BLUETOOTH_DEVICE_NAME "MyBluetoothDevice"
#define BLUETOOTH_DISCOVERY_TIMEOUT 5000 //5 second timeout
int main(int argc, char *argv[])
std::shared_ptr<QApplication> mainApplicationstd::make_shared<QApplication>(argc, argv);
//Error checking for no adapters and powered off devices
//omitted for sake of brevity
auto bluetoothAdapters = QBluetoothLocalDevice::allDevices();
std::shared_ptr<QBluetoothLocalDevice> localDevicestd::make_shared<QBluetoothLocalDevice>(bluetoothAdapters.at(0).address());
std::shared_ptr<QBluetoothDeviceDiscoveryAgent> discoveryAgentstd::make_shared<QBluetoothDeviceDiscoveryAgent>(localDevice.get());
std::shared_ptr<QBluetoothDeviceInfo> targetDeviceInfonullptr;
std::shared_ptr<QApplication> findBluetoothstd::make_shared<QApplication>(argc, argv);
auto setTargetDeviceInfo = [=](QBluetoothDeviceInfo info)
if (info.name() == TARGET_BLUETOOTH_DEVICE_NAME)
targetDeviceInfo = std::make_shared<QBluetoothDeviceInfo>(info);
discoveryAgent->stop();
findBluetooth->exit(0);
;
auto cancelDiscovery = [=]()
discoveryAgent->stop();
findBluetooth->exit(1);
;
auto startDiscovery = [=]()
discoveryAgent->start();
;
QObject::connect(discoveryAgent.get(), &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, setTargetDeviceInfo);
QTimer::singleShot(0, startDiscovery); //startDiscovery get called fine
QTimer::singleShot(BLUETOOTH_DISCOVERY_TIMEOUT, cancelDiscovery); //cancelDiscovery never gets called!
findBluetooth->exec();
//Now check if targetDeviceInfo is nullptr and run the real application etc...
mainApplication->exec();
【问题讨论】:
【参考方案1】:Answer:discoveryAgent->start();
基本上阻塞了你的主线程。这就是为什么 QTimer::singleShot(BLUETOOTH_DISCOVERY_TIMEOUT, cancelDiscovery);
发布的事件永远不会得到处理 - 应用程序正在执行 discoveryAgent->start()
并且没有机会查看事件循环。
【讨论】:
我输入了相同的答案。对我来说,当运行代码的 PC 或设备上未准备好蓝牙功能时,它会显示这种行为。将其移至工作线程是有意义的。 感谢您的快速回答。不幸的是,如果我注释掉对 discoveryAgent->start() 的调用(或删除第一个 singleShot),cancelDiscovery 仍然不会被调用。 你怎么知道的?我无法复制。 我发现了我的问题。在我的实际应用程序中,我已经在 main() 的开头创建了主 QApplication 实例,这导致第二个实例无法按预期工作。 是的,我编辑了我的主要帖子以反映这一点。对此感到抱歉,感谢您的宝贵时间。【参考方案2】:我原来的帖子有一个重要的遗漏:我遗漏了我已经在 main 开头实例化了主 QApplication 实例。创建两个 QApplication 实例是导致问题的原因。使用相同的 QApplication 实例而不是创建两个解决了该问题。
【讨论】:
以上是关于QTimer::singleShot 仅在间隔为 0 时调用 lambda的主要内容,如果未能解决你的问题,请参考以下文章
当 singleShot 为 True 时,QTimer 永远不会触发超时 [关闭]
QTimer::singleShot 在 qkeyevent 中不起作用