QT多发线程进行数据传输

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QT多发线程进行数据传输相关的知识,希望对你有一定的参考价值。

平时的项目程序中,经常需要处理多个串口和网络发送过来的数据,而且数据量还比较大,9600的波特率每秒钟至少1000个字节的数据需要处理并反映到界面上,一开始直接和UI主线程同一个线程,在x86的机器上跑还没问题,毕竟X86的机器最少主频也不会低于1.6G,但是如果数据量再更大或者到了ARM上跑,直接UI卡住不动,想到的解决办法就是用多线程,一个线程负责收数据,一个线程负责处理数据,当协议一样的时候,如果需要将数据解析从串口改为网络端口监听的数据,以前的办法是重新写一个tcp通信进行处理,这个并不是非常合理的办法,毕竟解析协议是一样的,所以自己总结了一个通用的数据处理思路:各种数据接收后排队的形式存入一个全局变量,单独开辟一个线程从这个全局变量中读取第一个数据,处理完则移除第一个数据,Qt中的链表直接提供了一个takeFirst函数,用起来非常爽!用while循环读取,在读取的时候加锁,这样的话就不会冲突了。
雏形:
全局变量文件

复制代码

  1. #ifndef APP_H

  2. #define APP_H


  3. #include "qstring.h"

  4. #include "qstringlist.h"


  5. class App

  6. {

  7. public:    

  8.     static QStringList list;


  9. };


  10. #endif // APP_H


复制代码

  1. #include "app.h"


  2. QStringList App::list=QStringList();


独立处理数据线程:

复制代码

  1. #ifndef TEST_H

  2. #define TEST_H


  3. #include "qthread.h"

  4. #include "qmutex.h"


  5. class Thread : public QThread

  6. {

  7.     Q_OBJECT

  8. public:

  9.     Thread();

  10.     ~Thread();


  11.     void stop();


  12. protected:

  13.     void run();


  14. private:

  15.     QMutex mutex;

  16.     volatile bool stopped;


  17. signals:

  18.     void readOne(QString txt);


  19. };


  20. #endif // TEST_H


复制代码

  1. #include "thread.h"

  2. #include "app.h"


  3. Thread::Thread()

  4. {

  5. stopped=false;

  6. }


  7. Thread::~Thread()

  8. {


  9. }


  10. void Thread::stop()

  11. {

  12.     stopped=true;

  13. }


  14. void Thread::run()

  15. {

  16.     while(!stopped){

  17.         mutex.lock();

  18.         if (App::list.count()>0){            

  19.             QString txt=App::list.takeFirst();

  20.             emit readOne(txt);

  21.         }

  22.         mutex.unlock();

  23.         msleep(1);//不加这句CPU占用率高达50%

  24.     }

  25.     stopped=false;

  26. }


主界面:

复制代码

  1. #ifndef WIDGET_H

  2. #define WIDGET_H


  3. #include <QWidget>

  4. #include "thread.h"

  5. #include "qtimer.h"


  6. namespace Ui {

  7. class frmMain;

  8. }


  9. class frmMain : public QWidget

  10. {

  11.     Q_OBJECT


  12. public:

  13.     explicit frmMain(QWidget *parent = 0);

  14.     ~frmMain();


  15. private slots:

  16.     void writeOne();

  17.     void readOne(QString txt);

  18.     void on_btnAppend_clicked();

  19.     void on_btnThread_clicked();

  20.     void on_btnTimer_clicked();


  21. private:

  22.     Ui::frmMain *ui;


  23.     QTimer *timer;

  24.     Thread *thread;


  25. };


  26. #endif // WIDGET_H


复制代码

  1. #include "frmmain.h"

  2. #include "ui_frmmain.h"

  3. #include "app.h"

  4. #include "qdatetime.h"

  5. #include "qdesktopwidget.h"


  6. #define _TIME_ qPrintable (QTime::currentTime().toString("now : hh:mm:ss:zzz"))


  7. frmMain::frmMain(QWidget *parent) :

  8.     QWidget(parent),

  9.     ui(new Ui::frmMain)

  10. {

  11.     ui->setupUi(this);


  12.     this->showMaximized();


  13.     timer=new QTimer(this);

  14.     timer->setInterval(50);

  15.     connect(timer,SIGNAL(timeout()),this,SLOT(writeOne()));


  16.     thread=new Thread;

  17.     connect(thread,SIGNAL(readOne(QString)),this,SLOT(readOne(QString)));

  18. }


  19. frmMain::~frmMain()

  20. {

  21.     delete ui;

  22. }


  23. void frmMain::writeOne()

  24. {

  25.     App::list.append(_TIME_);

  26. }


  27. void frmMain::readOne(QString txt)

  28. {

  29.     ui->txtOut->append(txt);

  30. }


  31. void frmMain::on_btnAppend_clicked()

  32. {

  33.     App::list.append(ui->txtIn->text());

  34. }


  35. void frmMain::on_btnThread_clicked()

  36. {

  37.     if (ui->btnThread->text()=="start thread"){

  38.         thread->start();

  39.         ui->btnThread->setText("stop thread");

  40.         ui->txtOut->append("start thread ok");

  41.     }else{

  42.         thread->stop();

  43.         ui->btnThread->setText("start thread");

  44.         ui->txtOut->append("stop thread ok");

  45.     }

  46. }


  47. void frmMain::on_btnTimer_clicked()

  48. {

  49.     if (ui->btnTimer->text()=="start timer"){

  50.         timer->start();

  51.         ui->btnTimer->setText("stop timer");

  52.         ui->txtOut->append("start timer ok");

  53.     }else{

  54.         timer->stop();

  55.         ui->btnTimer->setText("start timer");

  56.         ui->txtOut->append("stop timer ok");

  57.     }

  58. }


为了模拟大量数据,我这里开了50毫秒的定时器定时产生当前时间字符串的数据存入全局变量,然后放置了几个按钮用于手动添加字符串和开始停止线程及定时器。
技术分享


欢迎提出批评建议以及指点!谢谢!


以上是关于QT多发线程进行数据传输的主要内容,如果未能解决你的问题,请参考以下文章

Qt例子,线程间通信,如何在线程外部对线程进行控制,问题请看问题补充,多谢了先

QT中UI主窗口如何与子线程相互传递参数

qt子线程如何传输数据给主线程

qt中handler的定义

Qt同步线程(QMutex QMutexLocker QReadWriteLock QSemaphore QWaitCondition )

在不同的线程中拥有 Qt 只读模型和视图