【发布时间】:2020-03-06 04:16:33
【问题描述】:
我正在使用 QThreadPool 来运行具有创建然后清除巨大 QVector 并写入巨大文件大小的功能的工作程序。但是,每次一个工作人员到达那行(QVector::clear/QFile::close)时,所有线程都会冻结,并在完成后继续。
有人有什么建议可以克服这种情况吗?当在其中一个工作人员中运行这两个功能时,让其他线程仍然能够正常运行。对于 QFile::close,我尝试在迭代中使用 QFile::flush 而不是在迭代结束时使用 close(),但这对性能没有帮助。
这是清除向量时线程变慢时的代码
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
主窗口.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_start_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
主窗口.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h"
#include <QDebug>
#include <QSharedPointer>
#include <QThread>
#include <QThreadPool>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
on_start_pushButton_clicked();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_start_pushButton_clicked()
{
int numProcess = 20;
int numTraces = 10000;
int numSamps = 8680;
qDebug() << "main" << QThread::currentThread();
QThreadPool *pool = QThreadPool::globalInstance();
for (int i=0; i<numProcess; i++) {
worker *w= new worker;
w->setAutoDelete(true);
w->setData(i+1, numTraces, numSamps);
pool->start(w);
}
}
主窗口.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QPushButton" name="start_pushButton">
<property name="geometry">
<rect>
<x>240</x>
<y>50</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QRunnable>
#include <QThread>
class worker : public QObject, public QRunnable
{
Q_OBJECT
public:
explicit worker(QObject *parent = nullptr) : QObject(parent), QRunnable () {}
~worker() {}
void setData(int id, int numTraces, int numSamps);
void run();
signals:
public slots:
private:
void clearVector();
int id, numTraces, numSamps;
};
#endif // WORKER_H
worker.cpp
#include "worker.h"
#include <QCoreApplication>
#include <QDebug>
#include <QVector>
void worker::setData(int id1, int numTraces, int numSamps)
{
this->id = id1;
this->numTraces = numTraces;
this->numSamps = numSamps;
qDebug() << "setData" << id << numTraces << numSamps;
}
void worker::run()
{
clearVector();
qDebug() << "pool finished" << id << numTraces << numSamps << QThread::currentThread();
}
void worker::clearVector()
{
QVector<QVector<float>> traces1, traces2;
float progressWaypoint = 0.01f*numTraces;
int progressPos = 0;
for (int i=0; i<numTraces; i++) {
QVector<float> trace1, trace2;
for (int j=0; j<numSamps; j++) {
trace1.append(float(j));
trace2.append(float(numSamps - j));
}
traces1.append(trace1);
traces2.append(trace2);
if (numTraces <= 100) {
QCoreApplication::processEvents();
}
else {
if (i + 1 >= round(progressWaypoint*progressPos)) {
QCoreApplication::processEvents();
qDebug() << id << QThread::currentThread() << progressPos;
progressPos++;
}
}
}
traces1.clear();
traces2.clear();
}
【问题讨论】:
-
很久以前我也遇到过同样的问题。最后,我发现在调试版本中清理非常大的 Qt 容器类和刷新文件需要很长时间,但在发布版本中它们非常顺利。试试看,如果我必须添加这个作为答案,请通知我。
-
我在发布模式下尝试过,但不幸的是,当一个工作线程达到清除功能时,它的行为仍然相同
-
你为什么打电话给
QCoreApplication::processEvents()? -
另一个提示,调用
QThreadPool::globalInstance()->maxThreadCount()查看允许创建多少线程 -
当向量超出范围并被销毁时,它也会挂起相同的 w/out
QVector::clear()调用。顺便说一句,clear()实际上并没有取消分配内存(检查 Qt 文档),所以在这种情况下,它只会让事情变得更慢(而且这不是它挂起的地方,这在实际取消分配期间发生)。
标签: qt qt5 qthread qfile qvector