Multithreading 使用QT和GUI复制文件的正确方法避免冻结
我有一个应用程序,它使用Multithreading 使用QT和GUI复制文件的正确方法避免冻结,multithreading,qt,user-interface,freeze,qfile,Multithreading,Qt,User Interface,Freeze,Qfile,我有一个应用程序,它使用QFile::copy(..)将文件从一个位置复制到另一个位置。复制过程是在一个单独的线程中执行到一个worker对象中的,然而,有时候GUI会冻结,我在这里读了很多关于这个的主题,但是我知道这个方法(worker类)是正确的。我在其他项目上也采用同样的方法,在另一个线程(如计时器)中执行进程,它工作得非常好、平滑。似乎只有在复制文件时才会发生这种小冻结。在MS Windows中,“滞后”比在Linux中更为明显,在最后一种情况下,除非复制一个大文件(700MB),否则不
QFile::copy(..)
将文件从一个位置复制到另一个位置。复制过程是在一个单独的线程中执行到一个worker对象中的,然而,有时候GUI会冻结,我在这里读了很多关于这个的主题,但是我知道这个方法(worker类)是正确的。我在其他项目上也采用同样的方法,在另一个线程(如计时器)中执行进程,它工作得非常好、平滑。似乎只有在复制文件时才会发生这种小冻结。在MS Windows中,“滞后”比在Linux中更为明显,在最后一种情况下,除非复制一个大文件(700MB),否则不会检测到冻结,但只有在文件结束复制时,在复制过程中,GUI才会响应。我在我的main窗口(BUMain)
类中使用了这种方法:
void BUMain::initThreadSetup()
{
thread = new QThread;
Worker *worker = new Worker();
worker->moveToThread(thread);
connect(worker,SIGNAL(worker_Signal_updateProgressBar(int)),ui->progressBar,SLOT(setValue(int)),Qt::QueuedConnection);
connect(this,SIGNAL(main_signal_copyFile(int,QStringList,QString)),worker,SLOT(worker_Slot_copyFile(int,QStringList,QString)),Qt::QueuedConnection);
connect(worker,SIGNAL(worker_signal_keepCopying()),this,SLOT(main_slot_keepCopying()),Qt::QueuedConnection);
connect(worker,SIGNAL(worker_signal_logInfo(QString)),gobLogViewer,SLOT(logger_slot_logInfo(QString)),Qt::QueuedConnection);
connect(thread,SIGNAL(finished()),worker,SLOT(deleteLater()));
connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));
thread->start();
}
在MainGui(BUMain)构造函数中调用此方法以启动线程。一些相关代码:
这是在发出worker\u信号\u keepCopying()
时调用的插槽:
void BUMain::main_slot_keepCopying()
{
giProgress ++;
if(giProgress < giFileCounter){
emit(main_signal_copyFile(giProgress,gobPaths,ui->toFilesTextField->text()));
}
}
工人h:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QThread>
#include <QStringList>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
signals:
void worker_Signal_updateProgressBar(int value);
void worker_signal_keepCopying();
void worker_signal_logInfo(QString info);
public slots:
void worker_Slot_copyFile(int liIndex, QStringList files, QString path);
};
#endif // WORKER_H
我希望尽可能清楚,这有点难以解释。我以工人阶级的方法作为参考
注意:我使用QT5.1.1编程,使用Windows 10,使用Arch Linux部署应用程序
任何帮助或建议都将不胜感激。提前谢谢,祝你有愉快的一天 你的方法是正确的,如果有点冗长的话。“滞后”可能是由于内核愚蠢地管理页面缓存,并逐出应用程序的某些部分,以便为正在复制的文件中的页面腾出空间。唯一的补救办法可能是使用特定于平台的文件复制机制,该机制通知内核您将按顺序读取和写入,并且在完成写入后不再需要数据。有关详细信息和一些Linux代码,请参阅。在Windows上,人们希望
CopyFileEx
能够提供正确的建议,a.为您的答案提供了很多帮助。我来看看。顺致敬意,
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QThread>
#include <QStringList>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
signals:
void worker_Signal_updateProgressBar(int value);
void worker_signal_keepCopying();
void worker_signal_logInfo(QString info);
public slots:
void worker_Slot_copyFile(int liIndex, QStringList files, QString path);
};
#endif // WORKER_H
void Worker::worker_Slot_copyFile(int liIndex,QStringList files,QString path)
{
QString fileName;
for(int liIndex = 0; liIndex < files.length() - 1; liIndex ++){
fileName = QFileInfo(files.at(liIndex)).baseName()+"."+QFileInfo(files.at(liIndex)).completeSuffix();
if (QFile::exists(path+"/"+fileName))
{
QFile::remove(path+"/"+fileName);
}
QFile lobFile(files.at(liIndex));
if(lobFile.copy(path+"/"+fileName)){
emit(worker_signal_logInfo("File: " + fileName + " copied to: " + path));
emit(worker_Signal_updateProgressBar(liIndex+1));
}
}
}