c++ - 带有 Qt 事件循环的便携式通用共享库设置
问题描述
我们正在尝试编写一个可移植的共享库,它使用一些 Qt 类来方便(主要QTimer
是QTcpSocket
);不过,没有 GUI 的东西。相应的信号/插槽连接似乎需要一些 Qt 事件循环,因此我们按照此答案QCoreApplication
中的概述“启动” a 。因此,我们设置了一个工作对象来完成繁重的工作并将其移动到.QThread
我们现在遇到的问题是QThread
的所有者对象(在主线程内)和工作对象之间的排队连接QThread
似乎永远不会在 Linux 系统上得到处理,至少只要实现我们的库的程序确实如此不在主线程中提供它自己的任何进一步的 Qt 事件循环。这不是很有帮助,因为从工作线程传递到主线程的数据应该使用一些回调函数进一步传递,但现在这些函数永远不会被调用。
因此,我的问题是:有没有办法让事件循环在库主线程中工作而不会锁定它或主机程序(这似乎只是放一个QCoreApplication::exec()
或类似的情况)?或者我们是否必须建立不同的线程间通信方案(独立于 Qt)来处理这些数据传输?
由于我们不知道主机软件是否会在 a 上运行QApplication
,因此理想情况下,我还会在设置主线程事件循环之前对其进行检查。是一个简单的if(qApp != nullptr)
是否足够
PS:我尝试了一些但对我不起作用的东西:
- 设置一个
QEventLoop
在一个std::thread
(可能无法正常工作,因为仍然不在主线程中) QEventLoop
在主线程类中设置 a并processEvents()
使用 a 定期触发其功能QTimer
(可能由于缺少事件循环而无法正常工作QTimer::timeout
主函数中的信号缺少事件循环而无法正常工作)QCoreApplication
在 a 中启动std::thread
(在 Windows 上给出一个运行时警告 QCoreApplication 应该在主线程中启动)
解决方案
在 Qt 用语中,回调称为Qt::DirectConnection
. 但当然,这些回调将在您的工作线程上运行。但是任何其他使用回调的库都是这种情况,因此 Qt 在这里不是问题,您的代码也不是:基本思想具有此属性。
如果宿主应用程序没有使用事件循环(任何事件循环,不一定是 Qt 的),那么除了轮询之外你无能为力——见下文。
如果宿主应用程序运行 X11 事件循环,那么您需要确保您的 Qt 副本使用与宿主应用程序相同的底层事件循环。通常,这将是 glib 的事件循环,然后它应该自动工作。否则,您需要将 Qt 事件循环使用的同步原语的文件描述符传递给用户,并且用户需要将其集成到他们的事件循环中。无论您是否使用 Qt,您都将面临同样的问题:滚动您自己的通信方法不会修复它,因为您仍然需要一个可与用户正在使用的任何事件循环互操作的可等待原语。
用户当然可以随时轮询回调:公开一个mainPoll()
转发到QCoreApplication::processEvents()
.
推荐阅读
- powershell - 用于获取用户权利的 VSTS API 不起作用
- javascript - Firebase 函数 - 计算子项并更新条目
- python - Pandas 使用 numpy 数组列读取数据帧
- c# - Unity3d - 在 RTS 相机上拖放对象
- c++ - 如何创建一个 char *[] 变量,以便将其传递给函数
- java - 如何使用 selenium 处理 Phptravels.net 网站上的下拉菜单
- junit - 使用 PowerMock 进行文件操作的 JUnit 测试
- javascript - 在 iOS Safari 上打开文件/图像选择器时,现有异步请求因网络错误而失败
- java - 有条件地暴露 Spring Web 服务操作
- docker - 为什么在 Docker 中运行时 gunicorn worker 不启动?