QThread 与 QTimer 连接问题
QThread with QTimer connection issues
这有什么问题吗?它给我奇怪的编译错误:
candidate function not viable: no known conversion from 'void (QThread::*)(QThread::QPrivateSignal)' to 'const char *' for 2nd argument
QTimer timer;
timer.setInterval(3000);
connect(&timer, &QTimer::timeout, this, &ThisClass::runConnectionCheck);
QThread connectionThread;
timer.moveToThread(&connectionThread);
connect(&connectionThread, &QThread::started, &timer, &QTimer::start);
connectionThread.start();
connect(&connectionThread, &QThread::started, &timer, &QTimer::start);
因为QTimer::start有两个重载函数。您必须使用旧约定来指出使用哪一个。
connect(&connectionThread,SIGNAL(started()),&timer,SLOT(start()));
有 2 个 QTimer
槽称为 start()
,所以编译器有这种混淆,所以你应该 QOverload
:
connect(&connectionThread, &QThread::started, &timer, QOverload<>::of(&QTimer::start));
或static_cast<>()
:
connect(&connectionThread, &QThread::started, &timer,static_cast<void (QTimer::*)()>(&QTimer::start));
@KubaOber 提供 2 个选项:
C++14:
qOverload<>(&QTimer::start)
拉姆达:
[&]{ timer.start(); }
您一开始就遇到这个问题是您添加的并发症的结果:根本不需要连接。您可以立即启动计时器,然后移动它。在控件 returns 到定时器所在线程中的事件循环之前,定时器不会触发,并且在您的代码中不会发生这种情况,因为定时器在您的代码 [=17= 之前移动到另一个线程] 到此代码运行的事件循环(如果有的话)。
这段代码也能完成同样的工作:
// https://github.com/KubaO/Whosebugn/tree/master/questions/timer-move-start-53200294
#include <QtCore>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
int fired = 0;
QTimer timer;
QThread connectionThread;
QObject::connect(&timer, &QTimer::timeout, [&] {
Q_ASSERT(QThread::currentThread() == &connectionThread);
++fired;
timer.moveToThread(qApp->thread()); // move the timer back to allow destruction
QCoreApplication::quit();
});
timer.start(3000);
timer.moveToThread(&connectionThread);
Q_ASSERT(!fired);
connectionThread.start();
app.exec();
Q_ASSERT(fired);
connectionThread.quit();
connectionThread.wait();
}
这有什么问题吗?它给我奇怪的编译错误:
candidate function not viable: no known conversion from 'void (QThread::*)(QThread::QPrivateSignal)' to 'const char *' for 2nd argument
QTimer timer;
timer.setInterval(3000);
connect(&timer, &QTimer::timeout, this, &ThisClass::runConnectionCheck);
QThread connectionThread;
timer.moveToThread(&connectionThread);
connect(&connectionThread, &QThread::started, &timer, &QTimer::start);
connectionThread.start();
connect(&connectionThread, &QThread::started, &timer, &QTimer::start);
因为QTimer::start有两个重载函数。您必须使用旧约定来指出使用哪一个。
connect(&connectionThread,SIGNAL(started()),&timer,SLOT(start()));
有 2 个 QTimer
槽称为 start()
,所以编译器有这种混淆,所以你应该 QOverload
:
connect(&connectionThread, &QThread::started, &timer, QOverload<>::of(&QTimer::start));
或static_cast<>()
:
connect(&connectionThread, &QThread::started, &timer,static_cast<void (QTimer::*)()>(&QTimer::start));
@KubaOber 提供 2 个选项:
C++14:
qOverload<>(&QTimer::start)
拉姆达:
[&]{ timer.start(); }
您一开始就遇到这个问题是您添加的并发症的结果:根本不需要连接。您可以立即启动计时器,然后移动它。在控件 returns 到定时器所在线程中的事件循环之前,定时器不会触发,并且在您的代码中不会发生这种情况,因为定时器在您的代码 [=17= 之前移动到另一个线程] 到此代码运行的事件循环(如果有的话)。
这段代码也能完成同样的工作:
// https://github.com/KubaO/Whosebugn/tree/master/questions/timer-move-start-53200294
#include <QtCore>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
int fired = 0;
QTimer timer;
QThread connectionThread;
QObject::connect(&timer, &QTimer::timeout, [&] {
Q_ASSERT(QThread::currentThread() == &connectionThread);
++fired;
timer.moveToThread(qApp->thread()); // move the timer back to allow destruction
QCoreApplication::quit();
});
timer.start(3000);
timer.moveToThread(&connectionThread);
Q_ASSERT(!fired);
connectionThread.start();
app.exec();
Q_ASSERT(fired);
connectionThread.quit();
connectionThread.wait();
}