在寫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();
}