qt多线程网络编程(qt 多线程)

http://www.itjxue.com  2023-02-13 14:24  来源:未知  点击次数: 

QT 网络编程问题

先做一个QTcpServer作为监听socket,监听后如果出发newConnection信号,说明有连接进来。

然后通过nextPendingConnection()可以得到一个QTcpSocket,这就是用来和客户端进行通信用的套接字。

监听socket仍然可以继续监听。QTcpSocket可以用来和客户端通信。

如果通信负荷比较大,可以把每个客户端socket放入单独的线程(或进程)进行处理。负荷不大,则不需要。

qt多线程调用函数问题

主界面有两个按钮,点击“开始”按钮,触发一个信号,然后子线程打印一条信息,点击“结束”按钮,关闭线程

线程相关类定义如下

线程类变量定义如下

线程启动、信号槽及实现如下。在构造函数中通过thread.start()启动线程。

运行程序,并查看程序输出。点击一下“开始”按钮,会触发线程打印一条日志,再点击一下“开始”按钮,线程再次打印一条日志。点击“结束”按钮,打印线程结束。这时再点击“开始”按钮,线程将不再打印日志

修改线程打印函数为一个for循环,并在每次循环后sleep(5)秒

运行程序,然后点击“开始”按钮,线程开始打印日志。打印一两条后点击“结束”按钮,程序并没有停止打印日志,而是等到for循环结束后,才打印线程结束的日志。这说明线程并没有结束

修改线程结束函数如下,使用terminal函数。再次执行相同的步骤。

线程可以正常退出,但是程序关闭时崩溃。

修改线程打印函数,增加flag标识,在线程退出时,修改该flag标识,达到for循环退出的效果。这样线程可以正常退出,而且程序关闭时也不会崩溃

qt中如何实现多线程?

QT线程是独立的类:

在QT中添加C++类,头文件引用#include QThread;类公开,这样写:

class XXXX:public QThread,类里面申明Q_OBJECT,直接写在里面。signals: XXX();这是你的订阅事件名。private:void run();这是run函数;public: int cona=3;这是变量,一定要public。

cpp文件里引用头文件,run函数里面写方法:

void XXXX::run()

{

do

{

msleep(cona);

emit connec();

}while(true);

}

上面就是线程类了。现在我们在窗体中应用,先在头文件申明

头文件private: XXXX *thread1;XXXX *thread2;

构造函数中初始化他们

thread1=new XXXX();

thread1-cona=3;

QObject::connect(thread1,SIGNAL(connec()),this,SLOT(XXX信号1()));

thread2=new XXXX();

thread2-cona=4;

QObject::connect(thread2,SIGNAL(connec()),this,SLOT(XXX信号2()));

XXX信号1()是读A数据,XXX信号2()读B数据。

按钮1的信号槽里写方法同时进行每3秒读A、没4秒读B

thread1-start();

thread2-start();

要结束谁就用 xxxx-terminate();

看明白没?QT可不同与C++,你不熟悉编程环境,是很难理解的。

Qt如何进行创建多线程

在Qt中使用多线程,目前就我使用过的有两种,一是子类化QThread,重写run函数,在run函数里实现自己的代码,这一部分代码通常是比较耗时,或者干脆直接阻塞的。比如一个while循环,设置一个标志,判断循环结束。

这样的例子在网上有很多,就不写了。

这样写的话,会有一些东西需要了解。

子类化QThread的方法,只有run函数里面的内容是执行在子线程里的,其他的部分,比如槽函数什么的还是在主线程里执行(假设是在主线程开启的该子线程)。

还有一种方法,是子类化QObject,新建一个线程,然后使用MoveToThread把这个类的对象移到新建的线程中,这种做法使得它所有的槽函数都是执行在新开辟的线程里面。

如果直接(QObject对象).abc()的话,这个成员函数是在主进程内执行,可能会出现"QObject::killTimer: timers

cannot be stopped from another thread"的运行错误。

使用第二种方法的话,貌似会遇到这样的问题:如果在一个槽函数中把子线程阻塞,其他的槽函数无法接受来自主线程

Qt多线程里为什么我创建了多个线程,可每个线程的执行效率很低

多线程也是有代价的,在CPU和操作系统 上有明确的要求,否则反而达不到多线程的优势。

QT中的信号与事件,多线程

当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,将想要处理的信号和自己的一个函数(槽函数(slot))绑定并处理这个信号。

Qt信号槽-原理分析

信号与槽的连接方式

事件发生时,qt创建了一个代表它的对象,

一般的事件传递方式是调用virtual函数。可以把自己想做的处理写在当前函数,然后把其他的都传递给base类处理。

更通用的处理方式:

可以在事件处理之前先通过filter,阻止特定的event传递给target widget,通过installEventFilter和removeEventFilter控制。

用户可以自定义自己的事件,并生成一个实例,通过sendEvent()和postEvent()发送它们。

两种方式

原型:void QObject::moveToThread( QThread * targetThread )

改变该对象与线程之间执行的关系,并不改变谁拥有该对象,只是让该对象执行成员函数时利用了target thread。「在哪创建就属于哪」这句话放在任何地方都是适用的。

多线程

一、什么是Qt消息循环

Qt消息循环,就是从一个队列中不断取出消息,并响应消息的过程。窗体的鼠标、键盘、输入法、绘制,各种消息,都来自于Qt的消息循环。以Windows操作系统为例,Qt接管Windows原生窗口消息,并翻译成Qt的消息,派发给程序下的各个子对象、子QWidget等,通过接管层,可以很好屏蔽不同平台之间的差异性,开发人员不需要关心Windows或者X11的消息的差异性,只需要搞清楚各个QEvent之间是什么含义。

最开始的Qt消息循环开始于QCoreApplication::exec()。用户创建出一个QCoreApplication,或者说更多情况下是QApplication,执行QCoreApplication::exec(),一个应用程序便开始了。QCoreApplication会不断从操作系统获取消息,并且分发给QObject。

如果没有消息循环,那么Qt的信号和槽无法完全使用,有些函数也无法正确执行。举个例子,通过QueuedConnection连接的信号,其实是将一个事件压入了消息循环,如果没有QCoreApplication::exec(),那么这个消息循环将永远无法派发到指定的对象。

二、什么是线程相关性

准确点来说,应该是指QObject的线程相关性。以Qt文档中的示意图来作说明:

当我们创建一个QObject时,它会与创建自己所在的线程绑定。它参与的消息循环,其实是它所在线程的消息循环,如上图所示。假如某个线程没有默认的QThread::exec(),那么该线程上的QObject则无法接收到事件。另外,如果两个不同线程的QObject需要相互通信,那么只能通过QueuedConnection的方式,异步通知对方线程,在下一轮消息循环处理QObject的消息。

QObject的线程相关性默认会和它的parent保持一致。如果一个QObject没有parent,那么可以通过moveToThread,将它的线程相关性切换到指定线程。

了解QObject的线程相关性非常重要,很多初学者常常分不清一个多线程中哪些QObject应该由主线程创建,哪些应该由工作线程创建,我的观点是,它参与哪个消息循环,就由哪个来创建。

正因为这样的特性,我们才可以理解什么叫做AutoConnection。通过AutoConnect连接的两个QObject,如果是在同一个线程,那么可以直接调用(DirectConnection),如果不是在同一个线程,那么就通过事件通知的方式(QueuedConnection)来调用。通过信号和槽、事件或者QueuedConnection方式来进行线程间的通讯,尤其是与UI线程通讯,永远是最优雅的方式之一。

(责任编辑:IT教学网)

更多