美文网首页
QTcpSocket 在子线程执行测试笔记

QTcpSocket 在子线程执行测试笔记

作者: 茶色少年 | 来源:发表于2018-12-08 11:42 被阅读98次

本文是在子线程成创建QTcpSocke对象,并且向本地服务端在不同时刻发送不同指令。网上教程有很多,但发现大多数开启子线程的方式都是子类化QThread,然后在run()函数中写入需要执行的代码,但有篇博客强烈批评了该做法,主要原因请看以下两篇博客。

#include <QtCore>
#include <QTcpSocket>
class Worker : public QObject
{
    Q_OBJECT
public:
    ~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_OBJECT
signals:
    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)
错误实例化成员变量.png

所以在Conntect() 在对QTcpSocket进行了实例化,并通过Workder的析构函数回收其内存,防止内存泄漏。

正确运行结果如下图所示:


正确运行结果.png

从结果可以看到,Dummy::foo() 实际上是在主线程执行的,而通过信号/槽机制调用的Dummy的slot函数是在子线程中执行的。

个人总结

接触Qt时间很短,信号/槽机制、以及事件并不是特别熟悉,既然这个方式是正确的,就先学着吧。而这个方法可以看做是QThread对象开启了一个线程,然后可以将QObject的子类对象放进这个线程中,如果需要调用QObject子类对象的函数,需要通过信号/槽机制来实现。

相关文章

  • QTcpSocket 在子线程执行测试笔记

    本文是在子线程成创建QTcpSocke对象,并且向本地服务端在不同时刻发送不同指令。网上教程有很多,但发现大多数开...

  • iOS performSelector:withObject:a

    测试代码是在子线程中执行的,同时执行performSelector:withObject:afterDelay和p...

  • Qt多线程中基于队列实现网络通信

    基本思想 在线程中创建QTcpSocket对象实例; 在线程类中采用队列的方式动态添加需要执行的网络命令类实例; ...

  • Handler 测试题

    Handler 测试题 一,判断是否执行在子线程中 实际结果却是main 二,主线程如何给子线程发消息 主线程持有...

  • JS 异步理解

    一、异步 JS的异步:新开一个子线程,在主线程执行完之后,执行子线程, 第二个参数:时间,代表在子线程中等待执行的...

  • 关于线程安全问题

    一、 通过线程池创建A,B,C三个子线程,并设置A子线程执行1秒;B子线程执行3秒; C子线程执行7秒。要求:①主...

  • jmeter(2)-线程(用户)

    测试计划可以创建三种线程组 setUP线程组一种特殊类型的线程,可用于执行预测试操作。即执行测试前进行定期线程组的...

  • GCD线程延时

    //swift中的线程延时 //在主线程中延迟执行某动作,不会卡主主线程,不影响后面的东做执行 //在子线程中执行...

  • JMeter测试脚本编辑

    1、线程组,管理执行测试脚本的JMeter线程。JMeter线程,用来执行测试脚本里面的操作。 2、采样器,告诉J...

  • Java基础(五)-多线程-2

    问:如何实现子线程先执行,主线程再执行答: 启动子线程后,立即调用该线程的join()方法,则主线程必须等待子线程...

网友评论

      本文标题:QTcpSocket 在子线程执行测试笔记

      本文链接:https://www.haomeiwen.com/subject/cjqqhqtx.html