多线程中的信号与槽(下)

多线程中的信号与槽(下)

 

 

可以看到void TestThread::run() end...没有被调用

有趣的问题:
如果线程体函数中开启了事件循环,线程如何正确结束?
QThread::exec()使得线程进入事件循环
-事件循环结束前,exec()后的语句无法执行
-quit()和exit()函数用于结束事件循环
-quit()等价于exit(0),exec()的返回值由exit()参数决定

注意:
无论事件循环是否开启,信号发送后会直接进入对象所依附线程的事件队列;然而,只有开启了事件循环,对应的槽函数才会在线程中被调用

结束事件循环

 

设计相关的问题
什么时候需要在线程中开启事件循环?
设计原则:
事务性操作(间断性IO操作,等)可以开启线程的事件循环;每次操作通过发送信号的方式使得槽函数在子线程中执行。

文件操作就是一种事务性操作

概念小科普——文件缓冲区
-默认情况下,文件操作时会开辟一段内存作为缓冲区
-向文件中写入的数据会先进入缓冲区
-只有当缓冲区满或者遇见换行符才将数据写入磁盘
缓冲区的意义在于,减少磁盘的低级IO操作,提高文件读写效率。

文件操作示例:

看一个例子,每次write都向文件中写入数据,这就是一种事务性操作,一种比较低效的操作方式。

FileWriter.h

#ifndef FILEWRITER_H
#define FILEWRITER_H

#include <QObject>
#include <QFile>


class FileWriter : public QObject
{
    Q_OBJECT
    QFile m_file;
public:
    explicit FileWriter(QString file, QObject *parent = 0);

    bool open();
    void write(QString text);
    void close();
signals:

protected slots:

};

#endif // FILEWRITER_H
复制代码
#ifndef FILEWRITER_H
#define FILEWRITER_H

#include <QObject>
#include <QFile>


class FileWriter : public QObject
{
    Q_OBJECT
    QFile m_file;
public:
    explicit FileWriter(QString file, QObject *parent = 0);

    bool open();
    void write(QString text);
    void close();
signals:

protected slots:

};

#endif // FILEWRITER_H
复制代码

FileWriter.cpp

#include "FileWriter.h"

FileWriter::FileWriter(QString file, QObject *parent) :
    QObject(parent), m_file(file)
{

}

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

void FileWriter::write(QString text)
{
    m_file.write(text.toUtf8());
    m_file.flush();//将文件缓冲区中的数据写到磁盘上面
}

void FileWriter::close()
{
    m_file.close();
}

main.cpp

#include <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("E:/Qt/jackson.txt");

    if( writer.open() )
    {
        writer.write("D.T.Software
");
        writer.write("中文测试
");
        writer.write("狄泰软件
");
        writer.close();
    }

    return a.exec();
}
复制代码
#include <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("E:/Qt/jackson.txt");

    if( writer.open() )
    {
        writer.write("D.T.Software
");
        writer.write("中文测试
");
        writer.write("狄泰软件
");
        writer.close();
    }

    return a.exec();
}
复制代码

在main函数中,有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 writeSlots(QString text);
    void closeSlots();
};

#endif // 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 writeSlots(QString text);
    void closeSlots();
};

#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(writeSlots(QString)));
    connect(this,SIGNAL(doclose()),this,SLOT(closeSlots()));

    moveToThread(&m_worker);
    m_worker.start();
}

bool FileWriter::open()
{
    qDebug() << "bool FileWriter::open() = " << QThread::currentThreadId();
    return m_file.open(QIODevice::WriteOnly | QIODevice::Text);
}

void FileWriter::write(QString text)
{
    qDebug() << "void FileWriter::write(QString text)" << QThread::currentThreadId();
    emit doWrite(text);
}

void FileWriter::close()
{
    qDebug() << "void FileWriter::close()" << QThread::currentThreadId();
    emit doclose();
}

void FileWriter::writeSlots(QString text)
{
    qDebug() << "void FileWriter::writeSlots(QString text)" << QThread::currentThreadId();
    m_file.write(text.toUtf8());
    m_file.flush();//将文件缓冲区中的数据写到磁盘上面
}

void FileWriter::closeSlots()
{
    qDebug() << "void FileWriter::closeSlots()" << QThread::currentThreadId();
    m_file.close();
}

FileWriter::~FileWriter()
{
    m_worker.quit();
}
复制代码
#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(writeSlots(QString)));
    connect(this,SIGNAL(doclose()),this,SLOT(closeSlots()));

    moveToThread(&m_worker);
    m_worker.start();
}

bool FileWriter::open()
{
    qDebug() << "bool FileWriter::open() = " << QThread::currentThreadId();
    return m_file.open(QIODevice::WriteOnly | QIODevice::Text);
}

void FileWriter::write(QString text)
{
    qDebug() << "void FileWriter::write(QString text)" << QThread::currentThreadId();
    emit doWrite(text);
}

void FileWriter::close()
{
    qDebug() << "void FileWriter::close()" << QThread::currentThreadId();
    emit doclose();
}

void FileWriter::writeSlots(QString text)
{
    qDebug() << "void FileWriter::writeSlots(QString text)" << QThread::currentThreadId();
    m_file.write(text.toUtf8());
    m_file.flush();//将文件缓冲区中的数据写到磁盘上面
}

void FileWriter::closeSlots()
{
    qDebug() << "void FileWriter::closeSlots()" << QThread::currentThreadId();
    m_file.close();
}

FileWriter::~FileWriter()
{
    m_worker.quit();
}
复制代码

main.cpp

#include <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("E:/Qt/jackson.txt");

    if( writer.open() )
    {
        writer.write("D.T.Software
");
        writer.write("中文测试
");
        writer.write("狄泰软件
");
        writer.close();
    }

    return a.exec();
}
复制代码
#include <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("E:/Qt/jackson.txt");

    if( writer.open() )
    {
        writer.write("D.T.Software
");
        writer.write("中文测试
");
        writer.write("狄泰软件
");
        writer.close();
    }

    return a.exec();
}
复制代码

Qt线程的使用模式
-无事件循环模式
后台执行长时间的耗时任务
文件复制,网络数据读取,等

-开启事件循环模式
执行事务性操作
文件写入,数据库写入,等

原文地址:https://www.cnblogs.com/bruce1992/p/14321363.html