简体   繁体   English

调用Qt主线程

[英]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的主要方法有两种:

  1. You can derive QThread and rewrite QThread::run . 您可以派生QThread并重写QThread::run In that case you should do several things: 在这种情况下,您应该做几件事:

    • When creating your thread's object, do not specify parent; 创建线程的对象时,不要指定父对象; remove this object manually. 手动删除该对象。
    • In your thread's constructor call moveToThread(this) . 在线程的构造函数中,调用moveToThread(this)
    • In your thread's 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
  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM