換了新部門,對FPGA底層的使用不多,更多的是c和c++,於是開始了Qt界面的學習,在練習c和c++的同時,學習做界面,很多測試就不需要依賴別人。
Qt中的QThread類提供了平臺無關的線程。一個QThread代表了一個在應用程序中可以獨立控制的線程,它與進程中的其他線程分享數據,但是獨立執行的。相對於一般的程序都是從main()函數開始執行,QThread從run()函數開始執行。默認的,run()通過調用exec()來開啓事件循環並在線程內運行一個Qt事件循環。要創建一個線程,需要子類化QThread並且重新實現run()函數。
需要注意的是:
QThread只有run函數是在新線程裏的,其他所有函數都在QThread生成的線程裏
如果QThread是在ui所在的線程裏生成,那麼QThread的其他非run函數都是和ui線程一樣的,所以QThread的繼承類的其他函數儘量別要有太耗時的操作,要確保所有耗時的操作都在run函數裏。
在UI線程下調用QThread的非run函數(其實也不應該直接調用run函數,而應該使用start函數),和執行普通函數無區別,這時,如果這個函數要對QThread的某個變量進行變更,而這個變量在run函數裏也會被用到,這時就需要注意加鎖的問題,因爲可能這個變量前幾毫秒剛剛在run中調用,再調用時已經被另外的線程修改了。
我的理解:習慣了FPGA底層的並行處理,一時有些難以理解線程的處理。其實線程:通過並行處理方式,提高代碼的響應速度,處理方法類似於底層的流水線操作。例如我需要接收外部數據並顯示在界面上,假設外部每3秒發送一次數據,每次接收數據需要1.5秒,數據更新顯示需要2秒,如果串行處理所花費時間爲3.5秒,那麼數據會丟失,如果並行處理,那麼每次處理時間爲2秒。
實例使用:
新建工程,main函數使用默認代碼,添加線程類代碼和頭文件:
mthread.cpp:
#include "mthread.h"
#include <QDebug>
MyThread::MyThread(QObject *parent) :
QThread(parent)
{
stopped = false;
}
//run()函數的定義:
void MyThread::run()
{
while (!stopped)
{
qDebug() << QString("in MyThread: %1").arg(thr_num);
msleep(1000);
}
stopped = false;
}
void MyThread::stop()
{
stopped = true;
}
頭文件內容:
#include <QThread>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
void stop();
int thr_num;
protected:
void run();
private:
volatile bool stopped;
};
mainwindow.h修改:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QTimer>
#include "mthread.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void dealtimeout();
private:
Ui::MainWindow *ui;
MyThread *thread;
MyThread *thread2;
QTimer *timer;
};
#endif // MAINWINDOW_H
mainwindow.cpp修改如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
thread = new MyThread(this);
thread->thr_num=1;
thread2 = new MyThread(this);
thread2->thr_num=2;
timer = new QTimer(this);
timer->start(100);
connect(timer,&QTimer::timeout,this,&MainWindow::dealtimeout);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
thread->start();
thread2->start();
ui->pushButton->setEnabled(false);
ui->pushButton_2->setEnabled(true);
}
void MainWindow::on_pushButton_2_clicked()
{
thread->stop();
thread2->stop();
ui->pushButton->setEnabled(true);
ui->pushButton_2->setEnabled(false);
}
void MainWindow::dealtimeout()//更新LCD顯示器的數字
{
static int time = 0;
ui->lcdNumber->display(time);
time++;
}
運行結果如下:主線程在定時器修改LCD,兩個子線程在打印,子線程沒有運行順序之分。