Qt学习:迁移到子线程的变量应用处置

在写 Qt 过程中,目前会遇到大量数据处理,数据量 200W 以上,如果将处理数据操作在主线程中进行,会导致 UI 界面冻结,影响用户体验,所以将处理数据的过程迁移到子线程中是良好的处理手段,一般处理数据的对象都会定义为指针类型。代码如下:

    /***************************************************************************
     @date     2021-02-25
     @author   qiaowei
     @contact  [email protected]
     @version  1.0
     @brief    子线程,运行file_process_变量
    ***************************************************************************/
    QThread file_process_thread_;

    File_process* file_process_;

如果将对象迁移到子线程的步骤延后,就会有创建指针,迁移到子线程,创建指针,未迁移到子线程两种情况。代码如下:

void File_manager::start_thread(QThread& thread, QObject *process)
{
    if ( !thread.isRunning()) {

        process->moveToThread(&thread);
        connect(&thread, &QThread::finished, process, &QObject::deleteLater);
        thread.start();
    }
}

void File_manager::sl_open_file_to_split_data()
{
    QStringList opened_files = QFileDialog::getOpenFileNames();

    if (opened_files.isEmpty()) {
        return;
    }

    // 将处理文件数据对象迁入子线程,启动子线程
    start_thread(file_process_thread_, file_process_);

    emit si_files_name_of_split_data(opened_files);
}

void File_manager::sl_read_data_from_file()
{
    QStringList opened_files = QFileDialog::getOpenFileNames();

    if (opened_files.isEmpty()) {
        return;
    }

    // 将处理文件数据对象迁入子线程,启动子线程
    start_thread(file_process_thread_, file_process_);

    emit si_files_name_of_readed_data(opened_files);
}

所以,如何避免内存泄漏,正确处理好指针变量,应该在类的析构函数中有所考量。Qt 官方文档在构造函数中直接启动子线程,未将子线程延后:

class Controller : public QObject
 {
     Q_OBJECT
     QThread workerThread;
 public:
     Controller() {
         Worker *worker = new Worker;
         worker->moveToThread(&workerThread);
         connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
         connect(this, &Controller::operate, worker, &Worker::doWork);
         connect(worker, &Worker::resultReady, this, &Controller::handleResults);
         workerThread.start();
     }
     ~Controller() {
         workerThread.quit();
         workerThread.wait();
     }
 public slots:
     void handleResults(const QString &);
 signals:
     void operate(const QString &);
 };

在处理延后子线程数据时,要考虑创建的指针对象存在的线程,如果在主线程,说明没有启动子线程,直接 delete 即可,如果不在主线程中,则不用手动处理,调用子线程方法,系统会自动处理。我的处理代码如下:

File_manager::~File_manager()
{
    // 用户没有点击打开文件或拆分数据按钮,file_process_没有迁移到file_process_thread_线程中,需手动
    // 释放资源
    if (file_process_->thread() == thread()) {
        delete file_process_;
        file_process_ = nullptr;
    }

    file_process_thread_.quit();
    file_process_thread_.wait();
}

注:如果不确定指针是否为空指针,需要提前判断,当不为空指针时再进行删除操作,示例如下:

if ((nullptr != file_process_)
            && (file_process_->thread() == thread())) {
        delete file_process_;
        file_process_ = nullptr;
    }

    file_process_thread_.quit();
    file_process_thread_.wait();

你可能感兴趣的:(Qt&Pyside,C&C++,学习,qt,c++)