11 qt多线程

一个进程里可以有多个子线程,但只能有一个主线程(也有就main开始执行的线程).
主线程退出,其它所有的子线程会随着进程结束而结束,
QT进程的主线程其实就管理窗口的事件处理,当在窗口对象的函数里做死循环或耗时比较久的事情时,会引发界面不响应的状况。所以为了不让用户抓狂,耗时的工作就放在子线程里完成。

Qt里创建子线程有两种方法:

1 封装一个继承QThread的类,并实现虚函数run. 在run函数里写上此线程所作的工作.

    class MyThread : public QThread {
    public:
        void run() {
            //做线程要作的事情
            //此函数执行结束,线程也就退出工作了。所以这个函数通常都是个循环。
        }
    };

创建子线程对象时:

    MyThread * t = new MyThread;
    t->start(); //注意不是直接调用run函数,run函数是在线程启动后自动调用的。
            //调用start函数时,也可以指定线程的优先级别

线程对象与窗口对象通信时,需通过信号与槽的方法。
如实现:
在窗口里点击按钮时,创建出一个子线程并分配它的ID号, 此线程每隔5秒产生一个随机数,并传递给窗口对象(也就发出信号给窗口对象).

 mywin.h
#ifndef MYWIN_H
#define MYWIN_H
#include <QWidget>
#include <QPushButton>
#include <QThread>
class MyThread : public QThread
{
    Q_OBJECT
private:
    int id;
public:
    MyThread(int id); //创建线程对象时需分配ID
    void run();  //线程要做的事情
signals:
    void valGot(QString);  //线程的信号
};
//测试线程的窗口
class MyWin : public QWidget
{
    Q_OBJECT
private:
    QPushButton *btn;
    QList<MyThread *> list; //用于存放线程对象地址的链表
public:
    explicit MyWin(QWidget *parent = 0);
    ~MyWin();
signals:
public slots:
    void slot_btn(); //用于连接按钮的信号
    void slot_thread(QString str); //用于连接线程对象的信号
};
#endif // MYWIN_H
mywin.cpp
#include "mywin.h"
#include <QDebug>
MyThread::MyThread(int id)
{
    this->id = id;
}
void MyThread::run()
{
    int n;
    QString str("id=%1 : val=%2");
    while (1)
    {
        sleep(3);
        n = qrand()%100; //取100内的随机数
        emit valGot(str.arg(id).arg(n));
    }
}
///////////////////
MyWin::MyWin(QWidget *parent) : QWidget(parent)
{
    btn = new QPushButton("new thread", this);
    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slot_btn()));
    resize(320, 240);
}
MyWin::~MyWin()
{
    delete btn;
    //窗口对象退出时,把所有的子线程对象结束工作并回收资源。
    for (int i = 0; i < list.size(); i++ )
    {
        list.at(i)->terminate(); //终止线程对象的工作
        list.at(i)->wait(); //回收线程对象的资源
    }
}
void MyWin::slot_btn()
{
    static int id = 0; //用于分配线程的ID
    MyThread *t;
    t = new MyThread(id++);
    //连接线程对象的信号, 当线程对象的信号发出时,触发槽slot_thread
    connect(t, SIGNAL(valGot(QString)), this, SLOT(slot_thread(QString)));
    list.append(t); //把创建出来的线程对象的地址存入链表
    t->start(QThread::LowPriority); //启动线程,并指定此线程的优先级别比一般的线程要低
}
void MyWin::slot_thread(QString str)
{
    qDebug() << str; //输出线程对象发出的参数
}
main.cpp
#include <QApplication>
#include "mywin.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWin win;
    win.show();
    return a.exec();
}

2 第二种的方法有点像java里实现线程的接口。
首先还是封装一个类,要求必须继承QObject类或它的派生类。其实QT里QObject是所有类的基类,也就是说基本上只要继承一个QT里的类就可以了。
然后必须实现一个槽函数,函数名随便。如:

    class MyThread : public QObject
    {
        Q_OBJECT
    public slots:
        void  myslot();//函数里做线程处理的事件
    }

创建MyThread对象后, 还是需要一个QThread对象来处理事情

    MyThread *t = new MyThread;
    QThread *thread = new QThread;

    t->moveToThread(thread); //指定由线程对象thread来处理。
    //然后再把一个信号连接到MyThread的槽函数myslot
    thread->start();  //最后启动线程
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值