Qt工作笔记-moveToThread的基本使用以及让线程安全退出

程序运行截图如下:

这里是4个线程,对ListWidget进行输入,

使用MoveToThread,十分简单,但关闭的时候,会出现这样的提示:

造成这样的原因是:

循环还没有结束,线程就被我们关闭了。

解决方法如下:

1.重写关闭事件;

2.使用本地事件循环,先把循环退出后,再退出线程,即可,

程序源码如下:

insertlistitem.h

#ifndef INSERTLISTITEM_H
#define INSERTLISTITEM_H

#include <QObject>

QT_BEGIN_NAMESPACE
class QListWidget;
QT_END_NAMESPACE

class InsertListItem : public QObject
{
    Q_OBJECT
public:
    explicit InsertListItem(QListWidget *listWidget,QObject *parent = 0);
    void stopThread();

public slots:
    void beginToWork();


private:
    QListWidget *m_listWidget;
    bool m_runStatus;
};

#endif // INSERTLISTITEM_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QThread>

class InsertListItem;
class QTimer;

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;

private:
    Ui::Widget *ui;

    InsertListItem *m_list[4];
    QThread m_thread[4];
};

#endif // WIDGET_H

insertlistitem.cpp

#include "insertlistitem.h"
#include <QThread>
#include <QListWidget>
#include <QListWidgetItem>
#include <QTime>
#include <QDebug>

InsertListItem::InsertListItem(QListWidget *listWidget, QObject *parent) : QObject(parent)
{
    m_listWidget=listWidget;
    m_runStatus=true;
}

void InsertListItem::beginToWork()
{
    for(int i=0;i<1000;i++){
        if(!m_runStatus){
            break;
        }

        QString msg="ThreadId:"
                +QString::number((unsigned int)QThread::currentThreadId())
                +" "
                +" Time:"+QTime::currentTime().toString("HH:mm:ss");

        m_listWidget->insertItem(0,msg);
        QThread::sleep(1);
    }
}

void InsertListItem::stopThread()
{
    m_runStatus=false;
}

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "insertlistitem.h"
#include <QDebug>
#include <QMessageBox>
#include <QCloseEvent>
#include <QEventLoop>
#include <QTimer>


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    m_list[0]=new InsertListItem(ui->listWidget);
    m_list[0]->moveToThread(&m_thread[0]);

    m_list[1]=new InsertListItem(ui->listWidget_2);
    m_list[1]->moveToThread(&m_thread[1]);

    m_list[2]=new InsertListItem(ui->listWidget_3);
    m_list[2]->moveToThread(&m_thread[2]);

    m_list[3]=new InsertListItem(ui->listWidget_4);
    m_list[3]->moveToThread(&m_thread[3]);


    connect(&m_thread[0],SIGNAL(started()),m_list[0],SLOT(beginToWork()));
    m_thread[0].start();

    connect(&m_thread[1],SIGNAL(started()),m_list[1],SLOT(beginToWork()));
    m_thread[1].start();

    connect(&m_thread[2],SIGNAL(started()),m_list[2],SLOT(beginToWork()));
    m_thread[2].start();

    connect(&m_thread[3],SIGNAL(started()),m_list[3],SLOT(beginToWork()));
    m_thread[3].start();

}

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

void Widget::closeEvent(QCloseEvent *event)
{
    QMessageBox::StandardButton button=QMessageBox::information(this,"提示","退出",QMessageBox::Ok,QMessageBox::Cancel);
    if(button==QMessageBox::Ok){
        m_list[0]->stopThread();
        m_list[1]->stopThread();
        m_list[2]->stopThread();
        m_list[3]->stopThread();

        QEventLoop loop;
        QTimer::singleShot(1*1000,&m_thread[0],SLOT(terminate()));
        QTimer::singleShot(1*1000,&m_thread[1],SLOT(terminate()));
        QTimer::singleShot(1*1000,&m_thread[2],SLOT(terminate()));
        QTimer::singleShot(1*1000,&m_thread[3],SLOT(terminate()));
        QTimer::singleShot(1.5*1000,&loop,SLOT(quit()));
        QTimer::singleShot(2*1000,this,SLOT(close()));
        loop.exec();
        event->accept();
    }
    else{
        event->ignore();
    }
}

猜你喜欢

转载自blog.csdn.net/qq78442761/article/details/81660801