[英]Marshal calls to Qt main thread
I'm wrapping libcommuni, which uses Qt, in a different DLL project, which doesn't use Qt. 我将使用Qt的libcommuni包装在另一个不使用Qt的DLL项目中。 As far as I've been able to tell, I need to run the Qt message pump (via QCoreApplication
) to make sure networking, signals, etc. work properly. 据我所知,我需要运行Qt消息泵(通过QCoreApplication
)以确保网络,信号等正常工作。 However, I'm running in to some problems figuring out how to do just that. 但是,我遇到了一些问题,想方设法做到这一点。
Basically, I want to spin up a thread in the DLL, which calls QCoreApplication::exec()
and pumps all the Qt events. 基本上,我想在DLL中启动一个线程,该线程调用QCoreApplication::exec()
并泵送所有Qt事件。 I then want to marshal external calls to the DLL, which are on a different thread, to the Qt main thread, so I can safely use libcommuni. 然后,我想将对在另一个线程上的DLL的外部调用封送给Qt主线程,以便可以安全地使用libcommuni。
It looks like the recommended approach is to use signals and slots for this, but I've been unable to get that to work. 似乎推荐的方法是为此使用信号和插槽,但是我一直无法使其正常工作。 I create a signal on the QObject
class that is called via the DLL and I connect it to a slot on the QThread
that runs the Qt message pump. 我在通过DLL调用的QObject
类上创建一个信号,并将其连接到运行Qt消息泵的QThread
上的插槽。 However, if I specify Qt::QueuedConnection
when connecting the signal and slot, the message is never delivered when I emit the signal. 但是,如果在连接信号和插槽时指定Qt::QueuedConnection
,则在发出信号时永远不会传递消息。 If I omit Qt::QueuedConnection
altogether, the slot is called immediately on the calling thread rather than the Qt main thread. 如果我完全省略Qt::QueuedConnection
,则立即在调用线程而不是Qt主线程上调用该插槽。
I've also tried explicitly calling QCoreApplication::postEvent()
on the DLL thread to send an event to the Qt main thread, but event(QEvent)
is never called in the target QThread
. 我也尝试过在DLL线程上显式调用QCoreApplication::postEvent()
以将事件发送到Qt主线程,但是event(QEvent)
从未在目标QThread
。
Any ideas on what I'm doing wrong here? 对我在这里做错的任何想法吗? I'm guessing I'm not quite understanding Qt's threading model. 我猜我不太了解Qt的线程模型。
When you use QObject::connect
without specifying connection type - it uses Qt::AutoConnection
, which turns into Qt::DirectConnection
if the signal and slot are in a single thread, or into Qt::QueuedConnection
, if they are in different threads. 当您使用QObject::connect
不指定连接类型-它使用Qt::AutoConnection
,这变成Qt::DirectConnection
如果信号和槽是在单个线程中,或进入Qt::QueuedConnection
,如果它们是在不同的线程。 So, in your case, I can say, that for the moment, when you connect your signal with your slot, the objects, they belong to, are located in one thread. 因此,就您的情况而言,我可以说,目前,当您将信号与插槽连接时,它们所属的对象位于一个线程中。
In order to make Qt::QueuedConnection
work, you need an event loop in a thread, which contains slot. 为了使Qt::QueuedConnection
正常工作,您需要在包含插槽的线程中进行事件循环。
There are two main ways of using QThread: 使用QThread的主要方法有两种:
You can derive QThread
and rewrite QThread::run
. 您可以派生QThread
并重写QThread::run
。 In that case you should do several things: 在这种情况下,您应该做几件事:
moveToThread(this)
. 在线程的构造函数中,调用moveToThread(this)
。 run
method call exec after all initialization, but before all removal; 在所有初始化之后但在所有删除之前,在线程的run
方法中调用exec; thread will leave exec
right after you call QThread::quit
. 调用QThread::quit
之后,线程将立即退出exec
。 You can derive QObject
, create QThread
object, and call QThread::moveToThread
on your object (which, by the way, should be created without specifying parent) before calling QThread::start
. 你可以得到你QObject
,创建QThread
对象,并调用QThread::moveToThread
之前调用你的对象(其中,顺便说一下,应该没有指定父创建)上QThread::start
。
In your case I would recommend using the second method. 在您的情况下,我建议您使用第二种方法。
That is about threads, but I am not quite sure, your problem isn't connected with QCoreApplication::exec
. 那是关于线程的,但是我不太确定,您的问题与QCoreApplication::exec
没有关系。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.