我们正试图编写一个可移植的共享库,为方便起见使用一些Qt类(主要是QTimer
和QTcpSocket
);没有GUI的东西,但是。相应的信号/插槽连接似乎需要一些Qt事件循环,因此我们按this answer所述“准备” QCoreApplication
。因此,我们设置了一个工作对象来完成繁重的工作,并将其移动到QThread
。
我们现在遇到的问题是QThread
的所有者对象(在主线程内)和QThread
中的worker对象之间的排队连接似乎在Linux系统上从未得到处理,至少只要实现我们库的程序没有在主线程中提供自己的任何其他Qt事件循环即可。这不是很有帮助,因为应该使用一些回调函数进一步将从工作者传递到主线程的数据传递出去,但是这些回调函数现在永远不会被调用。
因此,我的问题是:有没有一种方法可以使事件循环在库主线程中工作而不会锁定它或将宿主程序锁定(这似乎只是在放置QCoreApplication::exec()
或类似内容时的情况)那里)?还是我们必须建立一个不同的线程间通信方案(独立于Qt)来处理这些数据传输?
由于我们不知道主机软件是否要在QApplication
上运行,因此理想情况下,我还要在设置主线程事件循环之前对此进行检查。一个简单的if(qApp != nullptr)
就足够了吗?
P.S .:我尝试过一些但对我不起作用的事情:
QEventLoop
中设置std::thread
(可能因为它不在主线程中而无法工作)QEventLoop
并使用processEvents()
定期触发其QTimer
函数(由于QTimer::timeout
缺少事件循环,可能无法正常工作主功能中的信号)QCoreApplication
中启动std::thread
(在Windows上发出运行时警告,应在主线程中启动QCoreApplication)答案 0 :(得分:0)
按照Qt的说法,回调称为Qt::DirectConnection
。但是,当然,这些回调将在您的工作线程上运行。但是其他任何使用回调的库都是这种情况,因此Qt在这里不是问题,您的代码也不是问题:基本概念具有此属性。
如果主机应用程序未使用事件循环(任何事件循环,不一定是Qt循环),那么除了轮询之外,您无能为力-参见下文。
如果主机应用程序运行X11事件循环,则需要确保Qt副本使用与主机应用程序相同的基础事件循环。通常,这将是glib的事件循环,然后它将自动运行。否则,您需要将Qt事件循环使用的同步原语的文件描述符传递给用户,并且用户需要将其集成到他们的事件循环中。无论是否使用Qt,您都将面临相同的问题:滚动自己的通信方法无法解决该问题,因为您仍然需要一个可等待的原语,该原语可以与用户正在使用的任何事件循环进行互操作。
用户当然可以在需要时轮询回叫:公开转发到mainPoll()
的{{1}}方法。
答案 1 :(得分:0)
尽管接受了另一个答案(我认为是更正确的),但我仍然想提一个出乎意料的解决方法:我们实际上通过连接辅助线程信号来解决了大多数系统上的事件循环/线程问题在设置工作程序的类的构造函数中使用lambda函数。
现在,我怀疑这种行为是否具有线程安全性,并且在file.save(os.path.join(app.root_path, "static/corporate_employee_images/", file_name))
函数调用中声明了相对较长的lambda函数当然不是很好的样式。但是,如果其他人最终都在这个问题上苦苦挣扎,这可能是一个短期解决方案或(临时)解决方法。