本节先讲解QThread,后续在讲后续几种。重点在于讲解,项目中遇到的问题,和解决办法。
class mythread:public QThread{
Q_OBJECT //因为QThread继承自QObject,所以要在子线程中实现信号,槽,就加上这一句。
protected:
void run();
}
具体以实际开发为准,例子以串口通信为准,重点在于主线程接受数据,子线程解析数,至于串口通信请看串口通信章节。
MainWindow :: MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
serial=new QSerialPort; //串口程序省略....... thread=new mythread; connect(serial, SIGNAL(readyRead()), this, SLOT(read_serial())); } 1:先解释为什么thread->start(),在接受数据的时候调用,而不是在创建线程的时候调用,因为在现实生活中, 数据传输是有延迟的,不可能一次性发送完毕, 如果:start()是在创建的时候调用,而数据有延迟多次接受才完成,那么第一次接受的数据会在run()函数里面的 执行,而第二次,第三次因为没有再次调用start(),所以 run()函数不会执行, 解决办法:在每次接受到数据的时候调用start(),从而执行run()函数。 2:上面说过一帧数据会分多次接收,这就是理论和实际情况的差距,既然主线程接受数据,子线程解析数据,那么 就会发生资源抢占,个人建议用信号量,在文档里把主次线程比作,生产者,消费者。 当主线程接受到一个字节的数据的时候,生产者会默认+1,当执行次线程的时候,生产者会-1.这可能是理想状态, 有可能主线程接受10个字节,次线程消费2个字节,这样生产的过快,消费的慢,为了防止生产的数据会覆盖掉 还没来得及消费的数据,这会只要生产者的容量达到4096我们设置的容量,生产者就会阻塞,不再接受数据,反过来 生产的慢,消费的快,为了避免解析垃圾数据,消费者也会阻塞。所以既解决了资源抢占,也解决了解析数据 这一块的难点,环buf机制。 说明:这里面的字节数根据需求定,默认是1,freeSpace.acquire(int num=1);usedSpace.release(int num=1);
QSemaphore freeSpace(4096); //生产者的最大容量,QSemaphore usedSpace(0); //消费者消费的容量void MainWindow::read_serial()
{QByteArray buf ;buf=serial->readAll();if(!buf.isEmpty()){freeSpace.acquire();//枷锁splite_str+=buf.toHex(); //splite_str为全局变量。//解锁usedSpace.release();}buf.clear();thread->start();} void mythread::run(){usedSpace.acquire();//枷锁QString str=splite_str.toLower();//splite_date(str);//解锁freeSpace.release();}