封装下QSerialPort的线程操作

QSerialPort坑也不少,写了个操作的基类,使用时请继承该类 ,在子类业务逻辑,不要轻易直接扩展该类。
原则上读操作应该放入同一个线程,写操作也要放入同一个线程。这里读操作(read)和写操作(打开,关闭,write)不放在一个线程里这里因为我需要方便获取串口打开判断返回值所以打开放到主线程里,而且一般情况下写数据量不是很大,所以这里所有的写操作放到主线程,读操作处理包常规放到次线程里。
如果串口写量很大,可以将所有操作放入线程里,比如用该类发信号进入打开关闭槽函数,但是打开之类的返回值需要在异步中,通过信号通知合适对象是否打开成功。

 头文件.h

#ifndef SINGLESERIALPORT_H
#define SINGLESERIALPORT_H
#include 
#include 

class QThread;
class QSerialPort;

//打开/关闭在主线程,读取发送在次线程
namespace SerialPort
{

class SingleSerialPort : public QObject
{
    Q_OBJECT
public:
    void SetPortName(QString);
    bool OpenPort();
    bool ClosePort();
    bool IsPortOpen();
    void WriteData(QByteArray);

public:
    explicit SingleSerialPort(QObject *parent = 0);
    virtual~SingleSerialPort();
    SingleSerialPort(SingleSerialPort&)=delete;
    SingleSerialPort&operator =(SingleSerialPort&)=delete;


protected:
    QString           port_name;        //串口名
    QSerialPort*      serial_port;      //串口对象
    QThread*          single_thread;    //线程
    QMutex            mutex;
    QByteArray        cache_bytes;      //缓存字节

signals:
    void WriteSig(QByteArray);
    void OpenPortSig();
    void ClosePortSig();

protected slots:
    virtual void  ReadFunSlot();
    bool          WriteDataSlot(QByteArray);
};
}

#endif // SINGLESERIALPORT_H

 

 实现文件.cpp

#include "SingleSerialPort.h"
#include
#include
#include 
using namespace SerialPort;
void SingleSerialPort::SetPortName(QString name)
{
    this->port_name=name;

    //其他值先写死 以后拓展可以放出来
    serial_port->setPortName(port_name);
    serial_port->setBaudRate(QSerialPort::Baud115200);
    serial_port->setDataBits(QSerialPort::Data8);
    serial_port->setParity(QSerialPort::NoParity);
    serial_port->setStopBits(QSerialPort::OneStop);
    serial_port->setFlowControl(QSerialPort::NoFlowControl);
}

bool SingleSerialPort::OpenPort()
{
    //作用域减少锁的粒度
    {
      QMutexLocker locker(&mutex);
      bool open = serial_port->open(QIODevice::ReadWrite);
      return open;
    }
}

bool SingleSerialPort::ClosePort()
{
     serial_port->close();  //一般情况都会成功
     return true;
}

bool SingleSerialPort::IsPortOpen()
{
      bool is_open=serial_port->isOpen();
      return is_open;
}

void SingleSerialPort::WriteData(QByteArray data)
{
  WriteDataSlot(data);
}

SingleSerialPort::SingleSerialPort(QObject *parent) : QObject(parent)
{
    serial_port=new QSerialPort();
    connect(serial_port, SIGNAL(readyRead()), this, SLOT(ReadFunSlot()), Qt::QueuedConnection);
   connect(this, SIGNAL(WriteSig(QByteArray)), this, SLOT(WriteDataSlot(QByteArray)), Qt::QueuedConnection);

   single_thread=new QThread;

   //放到线程中
   this->moveToThread(single_thread);
  //serial_port->moveToThread(single_thread); //这里不需要放入线程
   single_thread->start();  //线程开始
}

SingleSerialPort::~SingleSerialPort()
{   
//不能在删除thread之前删除QObject,因为QObject的代码将会在thread中执行,如果在删除QObject之后thread又刚好执行了QObject的代码,将会产生错误。

     //析构共享的资源
     if(serial_port)
     {
        delete serial_port;
        serial_port=NULL;
     }

    //较为优雅的结束线程
     if(single_thread)
     {
       single_thread->requestInterruption();
       single_thread->quit();
       single_thread->wait();
     }
}

void SingleSerialPort::ReadFunSlot()
{


}

bool SingleSerialPort::WriteDataSlot(QByteArray data)
{
    {
      QMutexLocker locker(&mutex);
      qint64 writeoksize = serial_port->write(data);
      bool flag = serial_port->flush();
      if ((writeoksize == data.size()) && flag)
      {
          return true;
      }
      else
      {
          return false;
      }
    }
}

 

你可能感兴趣的:(qt)