我有一个派生自 QThread
的类:class MyClass : public QThread
此类与另一个对象的槽相连。最初这是连接为 Qt::AutoConnection
。但是随后 - 一旦线程启动 (MyClass::run()
) - 信号不再“到达插槽”(为什么?)。
// connected before myObject->run()
s = QObject::connect(
_myObject, SIGNAL(signalLogMessage(const QString&, QtMsgType)),
this, SLOT(slotLogMessage(const QString&, QtMsgType)), Qt::DirectConnection);
我的第一个想法是我需要强制执行 Qt::QueuedConnection
(this
/_myObject
将是跨线程的)。在这种情况下,它根本不起作用。只有 Qt::DirectConnection
有效。线程启动后,恕我直言 Qt::QueuedConnection
是正确的选择(跨线程)。
知道出了什么问题吗?连接本身似乎是正确的,否则它无法正常工作(意味着甚至不能使用 Qt::DirectConnection
)。
编辑 1:-- 根据 hyde 的回答/Nikos 的评论
截至目前,我认为 hyde 的回答/Nikos 的评论指出了根本原因。我的 QThread
正在为另一个应用程序运行它自己的消息循环。这就是为什么它在自己的线程中运行并且基本上是一个无限循环的原因
run() {
// exec(); // while not reached
while (_runMessageLoop && ...) {
hr = CallDispatch(.....);
if (hr== 0) QThread::msleep(100);
// QCoreApplication::processEvents();
}
}
猜测由于这个无限循环,Qt 消息循环没有运行并且没有处理信号/槽(这是正确的吗?)当强制 Qt::DirectConnection
时,直接调用方法而没有 Qt需要消息循环,这可能是唯一可用的连接类型的原因。
现在的问题是,我如何将 Qt 和我自己的消息循环结合起来(如果可行的话)?无法在循环之前调用 exec()(因为它在 Qt 循环中),只有 QCoreApplication::processEvents();
在“我的循环”中仍然无法正常工作。
=> 在这里查看新问题:How to combine own message loop and Qt event loop?
最佳答案
没有看到所有代码很难说,但可能是因为:
QThread 对象本身不是线程,它是线程 Controller 。最重要的是,QThread 对象的线程亲和性不应该是它控制的线程。如果您的线程运行 Qt 事件循环,那么最好避免子类化 QThread。相反,将您的逻辑(线程间槽等)放在另一个 QObject 中,您可以在创建它之后将其移动到您使用 moveToThread 创建的线程。子类化 QThread 的唯一真正原因是用一个不调用 exec()
的方法覆盖 run()
方法。
相关阅读: https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
添加:
如果你覆盖 QThread::run(),你必须在那里调用 QThread::exec()
否则事件循环将不会运行并且没有非直接信号被传递到任何具有该线程的 QObject亲和性。如果你想拥有自己的事件循环,那是可能的,你只需要调用 QCoreApplication::processEvents()
处理 Qt 事件。
关于c++ - Qt 线程对象只发送信号作为 Qt :DirectConnection - why?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12982489/