第80课 - 多线程中的信号与槽(下)

版权声明:课程笔记内容整理于狄泰软件 https://blog.csdn.net/qq_39654127/article/details/81986388

1、有趣的问题 

如果线程体函数中开启了事件循环, 线程如何正常结束? 

 

QThread::exec()使得线程进入事件循环 

      - 事件循环结束前,exec()后的语句无法执行

      - quit() exit()函数用于结束事件循环 

      - quit()   ↔  exit(0) , exec()的返回值由exit()参数决定 

注意 

        无论事件循环是否开启,信号发送后会直接进入对

        象所依附线程的事件队列;然而,只有开启了事件

        循环,对应的槽函数才会在线程中被调用。 

2、编程实验 

结束事件循环    80-1.pro 

#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QThread>
#include "TestThread.h"
#include "MyObject.h"

int main(int argc, char *argv[])
{
    //同上节课代码

    t.start();

    t.wait(8 * 1000); //主线程等待t线程执行结束才向下运行,加上参数代表最多等待8s

    t.quit();

    return a.exec();
}

设计相关的问题 

           什么时候需要在线程中开启事件循环? 

设计原则 

         事务性操作(间断性IO操作,等) 可以开启线程的事件循环

         每次操作通过发送信号的方式使得槽函数在子线程中执行。 

 概念小科普-文件缓冲区

      -默认情况下,文件操作时会开辟一段内存作为缓冲区

      -向文件中写入的数据会先进入缓冲区 

      -只有当缓冲区满或者遇见换行符才将数据写入磁盘 

   缓冲区的意义在于,减少磁盘的低级IO操作,提高文件读写效率! 

3、编程实验 

文件操作示例 

FileWriter.h

#ifndef FILEWRITER_H
#define FILEWRITER_H

#include <QObject>
#include <QFile>
#include <QThread>

class FileWriter : public QObject
{
    Q_OBJECT

    class Worker : public QThread
    {
    protected:
        void run();
    };

    QFile m_file;
    Worker m_worker;
public:
    explicit FileWriter(QString file, QObject *parent = 0);
    bool open();
    void write(QString text);
    void close();
    ~FileWriter();
signals:
    void doWrite(QString text);
    void doClose();
protected slots:
    void writeSlot(QString text);
    void closeSlot();
};

#endif // FILEWRITER_H

FileWriter.cpp

#include "FileWriter.h"
#include <QDebug>

void FileWriter::Worker::run()
{
    qDebug() << "void FileWriter::Worker::run() - begin: tid = " << currentThreadId();

    exec();

    qDebug() << "void FileWriter::Worker::run() - end";
}

FileWriter::FileWriter(QString file, QObject *parent) :
    QObject(parent), m_file(file)
{
    connect(this, SIGNAL(doWrite(QString)), this, SLOT(writeSlot(QString)));
    connect(this, SIGNAL(doClose()), this, SLOT(closeSlot()));

    moveToThread(&m_worker); //当前类槽函数都在内部线程执行

    m_worker.start();
}

bool FileWriter::open()
{
    return m_file.open(QIODevice::WriteOnly | QIODevice::Text);
}

void FileWriter::write(QString text)
{
    qDebug() << "void FileWriter::write(QString text) tid = " << QThread::currentThreadId();

    emit doWrite(text);
}

void FileWriter::close()
{
    qDebug() << "void FileWriter::close() tid = " << QThread::currentThreadId();

    emit doClose();
}

void FileWriter::writeSlot(QString text)
{
    qDebug() << "void FileWriter::writeSlot(QString text) tid = " << QThread::currentThreadId();

    m_file.write(text.toAscii());
    m_file.flush(); //强制将缓冲区的内容写到磁盘
}

void FileWriter::closeSlot()//关闭文件也是事务性操作
{
    qDebug() << "void FileWriter::closeSlot() tid = " << QThread::currentThreadId();

    m_file.close();
}

FileWriter::~FileWriter()
{
    m_worker.quit();
}

main.cpp

#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QThread>
#include "FileWriter.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main() tid = " << QThread::currentThreadId();

    FileWriter writer("C:/Users/wss/Desktop/test.txt");

    if( writer.open() )
    {
        writer.write("D.T.Software\r\n"); //三次事务性操作,通过开启子线程完成,耗时在子线程上
        writer.write("中文测试\r\n");
        writer.write("狄泰软件\r\n");
        writer.close();
    }

    return a.exec();
}

Qt线程的使用模式

      -无事件循环模式 

               ★ 后台执行长时间的耗时任务 

                       ☛ 文件复制,网络数据读取,等 

      -开启事件循环横式 

               ★ 执行事务性操作 

                       ☛ 文件写入,数据库写入,等 

4、小结 

QThread ::exec()使得线程进入事件循环 

quit()等价于exit(0) , 用于结束线程的事件循环并返回 

事务性操作可以开启线程的事件循环,将操作分摊到子线程 

工程开发中,多数情况不会开启线程的事件循环 

线程多用于执行后台任务或者耗时任务 

猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/81986388