QTcpSocket 在子线程执行测试笔记
来源:互联网 发布:房子短租软件 编辑:程序博客网 时间:2024/06/05 07:50
本文是在子线程成创建QTcpSocke对象,并且向本地服务端在不同时刻发送不同指令。网上教程有很多,但发现大多数开启子线程的方式都是子类化QThread,然后在run()函数中写入需要执行的代码,但有篇博客强烈批评了该做法,主要原因请看以下两篇博客。
you are doing it wrong
Qt 的线程与事件循环——可打印threadid进行观察槽函数到底是在哪个线程里执行,学习moveToThread的使用)
另外也发现基于moveToThread方法来实现Tcp通讯的比较少,所以特意记录在此。
首先定义子类化QObject,
#include <QtCore>#include <QTcpSocket>class Worker : public QObject{ Q_OBJECTpublic: ~Worker() { if(tcp!=nullptr) { delete tcp; } }private: QTcpSocket *tcp; //int i;public: void foo() { qDebug()<<"Worker::Test get called from?: "<<QThread::currentThreadId(); }public slots: void Connect() { tcp = new QTcpSocket; tcp->connectToHost("127.0.0.1",110); tcp->waitForConnected(); } void onSend1() { tcp->write("Hello"); tcp->waitForBytesWritten(); //子线程ID号 qDebug()<<"Worker::Send get called from?: "<<QThread::currentThreadId(); } void onSend2() { tcp->write("Qt"); tcp->waitForBytesWritten(); //子线程ID号 qDebug()<<"Worker::Send get called from?: "<<QThread::currentThreadId(); }};
定义一个Dummy类用于与出现子线程:
class Dummy:public QObject{ Q_OBJECTsignals: void sendConnect();public: void Connect() { emit sendConnect(); }};
主函数:
#include "main.moc"int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); //主线程Id号 qDebug()<<"From main thread: "<<QThread::currentThreadId(); QThread t; QTimer timer; QTimer timer2; Worker worker; Dummy dm; QObject::connect(&dm,SIGNAL(sendConnect()),&worker,SLOT(Connect())); QObject::connect(&timer, SIGNAL(timeout()), &worker, SLOT(onSend1())); QObject::connect(&timer2,SIGNAL(timeout()),&worker,SLOT(onSend2())); //关键一步 worker.moveToThread(&t); //线程开启 t.start(); //向worker 发送连接请求 dm.Connect(); //猜猜下面这个函数在哪个线程执行? dm.foo(); timer.start(1000); timer2.start(1000); return a.exec();}
在此需要注意一点,对象内定义的成员变量是属于定义该对象的线程的,意思是Worker是在main()定义,那么Worker中定义的成员变量是属于主线程的,在其他slot函数中使用是属于跨线程使用。因此,如果在Worker的构造函数中对QTcpSocket进行实例化,那么执行上述方式的话,就会出现以下错误:
QObject: Cannot create children for a parent that is in a different thread.(Parent is QTcpSocket(0x111ba20), parent's thread is QThread(0x11117f0), current thread is QThread(0x68fe68)QObject: Cannot create children for a parent that is in a different thread.(Parent is QTcpSocket(0x111ba20), parent's thread is QThread(0x11117f0), current thread is QThread(0x68fe68)
所以在Conntect() 在对QTcpSocket进行了实例化,并通过Workder的析构函数回收其内存,防止内存泄漏。
正确运行结果如下图所示:
从结果可以看到,Dummy::foo() 实际上是在主线程执行的,而通过信号/槽机制调用的Dummy的slot函数是在子线程中执行的。
个人总结
接触Qt时间很短,信号/槽机制、以及事件并不是特别熟悉,既然这个方式是正确的,就先学着吧。而这个方法可以看做是QThread对象开启了一个线程,然后可以将QObject的子类对象放进这个线程中,如果需要调用QObject子类对象的函数,需要通过信号/槽机制来实现。
- QTcpSocket 在子线程执行测试笔记
- 子线程执行完后,主线程在执行场景
- C#将子线程附加在当前线程之后执行
- 子线程执行scheduledTimer
- 子线程执行方法
- 子线程执行进度条
- 执行主线程之后又执行了几个子线程,保证子线程执行完成在结束主线程
- 在子线程中 执行相关操作 请求网络
- 如何使主线程在子线程之后执行
- spring线程池,全部执行完子线程在执行主线程
- 将一个函数在主线程执行及子线程执行的方法
- java主线程等待所有子线程执行完毕在执行(常见面试题)
- java主线程等待所有子线程执行完毕在执行(常见面试题)
- OkHttp 执行流程与为什么Callback在子线程中执行
- java主线程等待所有子线程执行完毕在执行
- java主线程等待所有子线程执行完毕在执行(常见面试题)
- 子线程中执行定时器
- Android ThreadUtil 线程公共类,判断是否在主线程/ 子线程执行 相关操作
- python自动化测试unittest+selenium+HTMLTestRunner(一)
- elasticsearch安装
- Climbing Stairs
- fastjson、gson、jackson序列化和反序列化性能对比
- 快递查询API接口对接方法
- QTcpSocket 在子线程执行测试笔记
- FEP: 测试 lineage, 获得 CPU, MEMORY 统计信息
- 【TensorBoard】运行TensorBoard出现的错误汇总及相关的解决方案
- 封装函数与调用
- oracle_sql_检查未备份就被删除的归档日志
- Android防止button短时间内多次被点击(具体间隔时间可自由选取)
- Android实现轮播图
- Sublime Text 3 应用技巧和诀窍
- 表单校验总结