zoukankan      html  css  js  c++  java
  • 多线程中的信号与槽(下)

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

     

     

    可以看到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线程的使用模式
    -无事件循环模式
    后台执行长时间的耗时任务
    文件复制,网络数据读取,等

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

  • 相关阅读:
    java的eclipse集成开发环境中引入java web项目
    Uncaught SyntaxError: Unexpected identifier错误的解决方法
    layui框架和iframe总结 layui框架最简单的iframe版使用
    js不完全总结,除内置对象,DOM,BOM
    css简单总结
    机器学习之ID3决策树python算法实现
    python邮件发送正文,和图片,文件附件
    python邮件发送基础知识
    python实现带附件的邮件发送基于smtp协议
    Go语言之sync包 WaitGroup的使用
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14321363.html
Copyright © 2011-2022 走看看