也谈QT线程编程

来源:互联网 发布:原宿风 知乎 编辑:程序博客网 时间:2024/04/30 06:59

前几天遇到一个问题:

有一个类A

class A: public QWidget

一个类B

class B: public QThread

B在A中生成一个实例b

A中有一个按钮,点击后启动b,b要操作A中的lcdNumber实时显示一个数

问题来了,b的run()函数是如何声明的?

void B::run()
{
    ……

}

像这样吗?

void B::run()
{
    A::ui->lcdNumber->display(k);

}

编译不过去的。

因为GUI线程中的事件循环并没有做线程同步,如果直接利用非GUI线程操作界面的控件,会触发新的事件,因此可能会破坏GUI线程的事件循环

对于这种情况,需要采用信号、槽机制

我的例子如下:

头文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QThread>
#include "ui_widget.h"

namespace Ui {
    class Widget;
}

class MyThread : public QThread
{
    Q_OBJECT
signals:
    void signalOut();                           //这里我定义了一个信号
protected:
    void run();
};

class Widget : public QWidget {
    Q_OBJECT
public:
    Widget(QWidget *parent = 0);
    ~Widget();
    MyThread mythread;

protected:
    void changeEvent(QEvent *e);

private:
    Ui::Widget *ui;

private slots:
    void on_pushButton_clicked();
    void myshow();                              //这里我定义了一个槽
};

#endif // WIDGET_H

 

CPP文件:

#include "widget.h"
#include "ui_widget.h"

int k=0;

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(&mythread, SIGNAL(signalOut()), this, SLOT(myshow()));
}

Widget::~Widget()
{
    delete ui;
}

void Widget::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void Widget::on_pushButton_clicked()
{
    mythread.start();
}

void MyThread::run()
{
    while(1)
    {
        k++;
        if(k>99999)
            k=0;
        emit signalOut();
    }
}

void Widget::myshow()
{
    ui->lcdNumber->display(k);
}

大家可以试一试,你会发现功能实现了,但有死掉的趋势。界面好像响应不过来了。程序好像也是动一下停半天,数字变化不连续。

我们再加上一条语句

void MyThread::run()
{
    while(1)
    {
        k++;
        if(k>99999)
            k=0;
        emit signalOut();

        msleep(1);                                    //延时1毫秒
    }
}

一切都活了。

为什么会这样,看起来好像QT的开发小组为我们证明了“欲速则不达”。但显然这个线程在被系统拆分成时间片时发生了堵塞。

所以,在处理数据时,给你的程序一点喘息的时间,鞭打快牛是会被牛反踢一脚的。