Qt多线程使用

1、QThread
整体流程是创建一个工作的类,一个QThread类,然后将工作的类移到QThread线程中,连接4个信号与槽,其中是线程开始,线程结束,销户工作类和QThread类,当然工作类中要额外定义一个工作结束的信号

点击查看代码
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr);
    void DoWork();//执行任务
signals:
    void WorkOver();//任务结束的信号
};
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    Worker*worker;
    QThread*thread;
};
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->thread=new QThread();
    this->worker=new Worker();
    //将worker移入线程
    worker->moveToThread(thread);
    //当线程开始时执行DoWork()
    connect(this->thread,&QThread::started,this->worker,&Worker::DoWork);
    //工作对象发送任务结束信号,线程停止
    connect(this->worker,&Worker::WorkOver,this->thread,&QThread::quit);
    //工作对象发送任务结束信号,通知自己延后把自己删除
    connect(this->worker,&Worker::WorkOver,this->worker,&Worker::deleteLater);
    //线程结束后,延迟删除这个线程
    connect(this->thread,&QThread::finished,this->thread,&QThread::deleteLater);

    //准备工作做好后,启动线程
    this->thread->start();
}
2、QtConcurrent QtConcurrent是Qt自定义封装的一个线程池,不需要自己创建线程,直接在run中调用对应方法就可以,不过waitForFinished()这个方法会阻塞主线程 使用前先在.pro中添加Qt+=concurrent
点击查看代码
void Worker::ProcessData(int a)
{
    for(int i=0;i<10;i++)
        qDebug()<<i+a;
}
void MainWindow::on_pushButton_clicked()
{
    //通过QtConcurrent在线程池中调用lambda
    QFuture<void>future=QtConcurrent::run([this]{
        this->worker->ProcessData(10);
    });
    future.waitForFinished();//会阻塞主线程
    //通过QtConcurrent使用多个数据
    QVector<int> arr={0,1,2,3,4};
    QFuture<void>future1 = QtConcurrent::map(arr,[this](int item){
        this->worker->ProcessData(item);
    });
    future1.waitForFinished();
}
在此之后,我使用QtConcurrent写了一个子线程操作数据,操作好后发信号给主线程,主线程更新QChart表格的小demo
点击查看代码
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr);
    void DoWork();
    void ProcessData();//处理数据
    QVector<int>data;
signals:
    void WorkOver(int a,int b);
private:
    int a=0;
    int b=0;
};
void Worker::ProcessData()
{
    if(a>5&&b>5)
        return;
    emit WorkOver(this->a,this->b);
    this->a++;
    this->b++;
    qDebug()<<"a:"<<a<<" b:"<<b;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
    Worker*m_worker;//处理坐标数据
    QLineSeries*m_series;//图表的曲线
    QChart *m_chart;//图表
    QChartView*m_chartView;//承载图表的画布
    QTimer*m_timer=nullptr;
    QMutex m_mutex;
};
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->m_worker=new Worker();
    this->m_series=new QLineSeries();
    this->m_series->setName("数据曲线");

    this->m_chart=new QChart();
    this->m_chart->addSeries(this->m_series);
    this->m_chart->setTitle("数据测试图表");
    //this->m_chart->createDefaultAxes(); // 自动创建坐标轴

    //手动设置X,Y轴
    QValueAxis*axisX=new QValueAxis();
    QValueAxis*axisY=new QValueAxis();
    axisX->setTitleText("X轴");
    axisY->setTitleText("Y轴");
    axisX->setMin(0);               // 最小值
    axisX->setMax(5);               // 最大值
    axisY->setMin(0);
    axisY->setMax(10);
    axisX->setTickCount(6);         // 刻度数量
    //设置到chart中
    this->m_chart->setAxisX(axisX,this->m_series);
    this->m_chart->setAxisY(axisY,this->m_series);

    this->m_chartView=new QChartView(this->m_chart);//创建背景画布
    this->m_chartView->setRenderHint(QPainter::Antialiasing);//平滑曲线
    setCentralWidget(this->m_chartView);//将画布设置在中间
    this->resize(800,500);
    //接受到Worker的信号就更新表格
    connect(this->m_worker,&Worker::WorkOver,[this](int a,int b){
        qDebug()<<"已接受到"<<a<<" "<<b;
        this->m_series->append(a,b);
    });
    QtConcurrent::run([this]{
        while(1)
        {
            {
                QMutexLocker locker(&this->m_mutex);
                this->m_worker->ProcessData();//处理数据
            }
            QThread::msleep(1000);
        }
    });
如果用时间间隔来触发轮询更新的话,我又用了QFutureWatcher来监听QtCurrent的线程运行结果,如果运行结束就触发对应图表更新的槽函数 当然还有个时间间隔的信号与槽,每0.5s就触发多线程添加处理数据的任务
点击查看代码
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void init_draw();//初始化图表
private:
    Ui::MainWindow *ui;
    Worker*m_worker;//处理坐标数据
    QLineSeries*m_series;//图表的曲线
    QChart *m_chart;//图表
    QChartView*m_chartView;//承载图表的画布
    QTimer*m_timer=nullptr;
    QMutex m_mutex;
    QFutureWatcher<void>* m_watcher; // 监听异步任务
};
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->init_draw();//初始化图表
    this->m_timer=new QTimer();
    this->m_timer->setInterval(500);//间隔0.5s

    this->m_worker=new Worker();
    this->m_watcher=new QFutureWatcher<void>();//任务监听
    //监听到任务结束,触发更新图表
    connect(this->m_watcher,&QFutureWatcher<void>::finished,[this]
    {
        QMutexLocker locker(&this->m_mutex);
        qDebug()<<"已接受到"<<this->m_worker->get_a()<<" "<<this->m_worker->get_b();
        this->m_series->append(this->m_worker->get_a(),this->m_worker->get_b());
    });
    connect(this->m_timer,&QTimer::timeout,[this]
            {
            //如果任务忙就返回,不创建新的任务
            if (m_watcher->isRunning())
            {
                return;
            }
            QFuture<void>future=QtConcurrent::run([this]{
            QMutexLocker locker(&this->m_mutex);
            this->m_worker->ProcessData();//处理数据
            QThread::msleep(1000);
        });
        this->m_watcher->setFuture(future);//设置监管的future
    });
    this->m_timer->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}
//初始化图表
void MainWindow::init_draw()
{
    this->m_series=new QLineSeries();
    this->m_series->setName("数据曲线");

    this->m_chart=new QChart();
    this->m_chart->addSeries(this->m_series);
    this->m_chart->setTitle("数据测试图表");
    //this->m_chart->createDefaultAxes(); // 自动创建坐标轴

    //手动设置X,Y轴
    QValueAxis*axisX=new QValueAxis();
    QValueAxis*axisY=new QValueAxis();
    axisX->setTitleText("X轴");
    axisY->setTitleText("Y轴");
    axisX->setMin(0);               // 最小值
    axisX->setMax(5);               // 最大值
    axisY->setMin(0);
    axisY->setMax(10);
    axisX->setTickCount(6);         // 刻度数量
    //设置到chart中
    this->m_chart->setAxisX(axisX,this->m_series);
    this->m_chart->setAxisY(axisY,this->m_series);

    this->m_chartView=new QChartView(this->m_chart);//创建背景画布
    this->m_chartView->setRenderHint(QPainter::Antialiasing);//平滑曲线
    setCentralWidget(this->m_chartView);//将画布设置在中间
    this->resize(800,500);
}

posted on 2026-06-11 13:18  dd_l  阅读(3)  评论(0)    收藏  举报