Qt Thread对象只发送信号为Qt:DirectConnection - 为什么? [英] Qt Thread object only sending signal as Qt:DirectConnection - why?

查看:158
本文介绍了Qt Thread对象只发送信号为Qt:DirectConnection - 为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类派生自 QThread class MyClass:public QThread
此类连接与另一个对象的插槽。最初这是连接为 Qt :: AutoConnection 。但是,一旦线程启动( MyClass :: run()) - 信号不再到达槽(为什么? strong>)。

  //在myObject-> run之前连接
s = QObject :: connect b $ b _myObject,SIGNAL(signalLogMessage(const QString& QtMsgType)),
this,SLOT(slotLogMessage(const QString& QtMsgType)),Qt :: DirectConnection);

我的第一个想法是我需要强制 Qt :: QueuedConnection this / _myObject 将交叉线程)。在这种情况下,它根本不工作。只有 Qt :: DirectConnection 可以工作。线程启动后,IMHO Qt :: QueuedConnection 是正确的选择(交叉线程)。



任何想法是什么问题?连接本身似乎是正确的,否则它不工作(意味着即使不用 Qt :: DirectConnection )。



编辑1: - 截至海德的回答/ Nikos的评论



回答/ 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循环中),只是在my循环中的 QCoreApplication :: processEvents(); 工作。



=>请参阅这里的新问题: Qt:如何结合自己的消息循环和Qt事件循环?

解决方案

很难说没有看到所有的代码,但它可能是因为:



QThread对象本身不是线程,它的线程控制器。最重要的是,QThread对象的线程亲和力应该不是它控制的线程。如果你的线程运行Qt事件循环,那么最好避免子类化QThread。相反,在另一个QObject中有你的逻辑(线程间隙等),你移动到创建它之后用moveToThread创建的线程。子类QThread的唯一真正原因是覆盖 run()方法,不使用 exec() / p>

相关阅读:
http://blog.qt.digia.com/2010/06/17/youre-doing-it-wrong/



添加:
如果你重写QThread :: run(),你必须调用 QThread :: exec()并且没有非直接信号被传递到具有该线程亲和力的任何QObject。如果你想有自己的事件循环,这是可能的,你只需要调用 QCoreApplication :: processEvents() 来处理Qt事件。


I have a class derived from QThread: class MyClass : public QThread This class is connected with a slot of another object. Originally this was connected as Qt::AutoConnection. But then - as soon as the thread is started (MyClass::run()) - the signal is no longer "reaching the slot" (why?).

// connected before myObject->run()
s = QObject::connect(
_myObject, SIGNAL(signalLogMessage(const QString&, QtMsgType)), 
this, SLOT(slotLogMessage(const QString&, QtMsgType)), Qt::DirectConnection);

My first idea was that I need to force Qt::QueuedConnection (this / _myObject will be cross threaded). In this case it does not work at all. Only Qt::DirectConnection works. After the thread is started, IMHO Qt::QueuedConnection is the correct choice (cross thread).

Any idea what is going wrong? The connection itself seems to be correct, otherwise it was not working at (mean even not with Qt::DirectConnection).

Edit 1: -- As of hyde's answer / Nikos' comment

As of right now I think hyde's answer / Nikos' comment are pointing out the root cause. My QThread is running it's own message loop for another application. This is the reason why it is running in its own thread and is basically an infinite loop

run() { 
  // exec(); // while not reached    
  while (_runMessageLoop && ...) {
    hr = CallDispatch(.....);
    if (hr== 0) QThread::msleep(100); 
    // QCoreApplication::processEvents();
  }
}

Guess due to this infinite loop the Qt message loop is not running and no signal / slots are processed (is this correct?) When forcing Qt::DirectConnection the methods are called directly with no Qt message loop required, this might be the reason why this is the only connection type working.

The question is now, how can I combine the Qt and my own message loop (if this is feasible)? Cannot call exec() before the loop (because then it is in the Qt loop), and just the QCoreApplication::processEvents(); in "my loop" is still not working.

=> see new Question here: Qt: How to combine own message loop and Qt event loop?

解决方案

Hard to say without seeing all the code, but it may be because of this:

QThread object itself is not the thread, it's the thread controller. Most importantly, QThread object's thread affinity should not be the thread it controls. If your thread runs Qt event loop, then it's best to avoid subclassing QThread. Instead, have your logic (inter-thread slots etc) in another QObject, which you move to the thread you created with moveToThread after creating it. Only real reason to subclass QThread is to override run() method with one which does not call exec().

Related reading: http://blog.qt.digia.com/2010/06/17/youre-doing-it-wrong/

Additon: If you override QThread::run(), you have to call QThread::exec() there or event loop won't be running and no non-direct signal gets delivered to any QObject with that thread affinity. If you want to have your own event loop, that is possible, you just have to call QCoreApplication::processEvents() to process Qt events.

这篇关于Qt Thread对象只发送信号为Qt:DirectConnection - 为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆