跨 Qt 线程共享数据 [英] Sharing data across Qt threads

查看:83
本文介绍了跨 Qt 线程共享数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Qt 的新手,所以请原谅这个问题的简单性,但我对 Qt 线程有点困惑.假设我有 3 个线程:主要的默认 GUI 线程和我自己创建的 2 个线程(称为 WorkerThread).我的每个 WorkerThread 都继承自 QThread 并且是永久线程,它们经常唤醒并从套接字发送数据并在 GUI 元素上发布状态.1) 允许 GUI 线程在 WorkerThread 线程可以使用的 WorkerThread 对象中设置数据的最佳方法是什么?2) 允许 WorkerThread 将状态发送到 GUI 线程以显示给用户?3) 允许两个 WorkerThread 使用同一个套接字?

I'm new to Qt so please excuse the simplicity of the question but I'm a bit confused on the Qt threading. Let's say I have 3 threads: the main default GUI thread, and 2 threads of my own creation (called WorkerThread). Each of my WorkerThreads inherits from QThread and are permanent threads that every so often wake up and send data out a socket and post status on a GUI element. How is the best way to 1) allow the GUI thread to set data in the WorkerThread object that the WorkerThread thread can use? 2) allow the WorkerThread to send status to the GUI thread to be displayed for the user? 3) Allow both WorkerThreads to use the same socket?

从文档看来,当我创建一个 WorkerThread 对象时,它由创建线程拥有(除了作为新线程的 run 方法).那么如何为新线程设置数据执行呢?新线程使用的所有数据都必须是全局的吗?例如,我希望 GUI 允许用户为每个 WorkerThreads 选择一个数据包类型,以便在它们醒来时发送.我曾假设我会在 WorkerThread 中放入一些插槽,GUI 线程会发出信号.当 WorkerThread 对象接收到 SetPacketType 的信号时,它将设置一个成员变量,run 方法在每次迭代时引用该变量.但是在阅读了文档后,我不确定这是不是这样做的方法.如果 WorkerThread 对象由创建线程(在本例中为 GUI 线程)拥有,那么向它发送信号不会跨越线程边界,是吗?

It seems from the documentation that when I create a WorkerThread object it is owned by the creating thread (except for the run method that is a new thread). So how does one set data for the new thread to execute on? Must all the data the new thread uses be global? For instance, I would like the GUI to allow the user to select a packet type for each of the WorkerThreads to send when they wake up. I had assumed that I would put in some slots in the WorkerThread that the GUI thread would signal. When the WorkerThread object received a signal to SetPacketType it would set a member variable that the run method references on each iteration. But after reading the documentation I'm not sure that is the way to do it. If the WorkerThread object is owned by the creating thread (GUI thread in this case) then sending signals to it doesn't cross thread boundaries does it?

此外,跨线程共享套接字连接的正确技术是什么?

Also, what is the proper technique for sharing the socket connection across threads?

提前致谢.

推荐答案

使用 Qt,在线程之间发送信息的最简单方法是使用信号和槽.Qt 自动为线程之间的连接使用排队信号(参见 Qt::ConnectionType),保证一个信号可以从一个线程发出,但是slot会在接收者对象的线程中执行.

With Qt, the easiest way to send information between threads is to use signals and slots. Qt automatically uses queued signals for connections between threads (see Qt::ConnectionType), which ensures that a signal can be emitted from one thread, but the slot will be executed in the thread of the receiver object.

如果在线程之间发送的数据(要完成的工作或状态信息)是 Qt 可以自动排队的东西(例如,QStrings、int 和 double 等内置类型等),则将信息作为信号/插槽的参数是发送信息的最佳方式.如果共享大型或复杂数据,则您需要使用 qRegisterMetaType 允许 Qt 复制数据,或传递指向线程安全对象的指针.与 Pie_Jesu 所说的不同,线程确实共享一个地址空间,因此您可以共享指针;只需确保一个线程与共享对象的交互不会干扰另一个线程的交互.

If the data being sent between threads (work to be done or status information) is something that Qt can automatically queue (e.g., QStrings, built-in types like int and double, and others), then passing the info as the arguments to the signal/slot is the best way to send the info. If large or complex data is being shared, then you either need to use qRegisterMetaType to allow Qt to copy the data, or pass a pointer to a thread-safe object. Unlike what Pie_Jesu said, the threads do share an address space so you can share pointers; just make sure that one thread's interaction with the shared object won't interfere with another thread's interactions.

QTcpSocket 不是线程安全的(根据 Qt 的文档,它只是可重入的),因此如果您共享套接字,则必须负责确保线程不会以冲突的方式使用套接字.

QTcpSocket is not thread-safe (it's only reentrant according to Qt's documentation), so if you share the socket you will have to be responsible for ensuring that threads don't use the socket in conflicting ways.

这篇关于跨 Qt 线程共享数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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