Копирование большого файла в основном потоке приложения замораживает его интерфейс. Копирование в отдельном потоке не помогает. Подскажите, пожалуйста, почему интерфейс всё равно замерзает.
1. QtConcurrent::run. Начал с простого.
Выделяю копирование в отдельную функцию
void MainWindow::fileCopy(const QString &source, const QString &destination)
{
QFile::copy(source, destination);
}
Само копирование:
QString source = "D:\Distrib\rlink20022014.rar";
QString destination = "\\Distrib\rlink20022014.rar"; //копирую в сетевую папку
QFuture<void> f1 = QtConcurrent::run(this, &MainWindow::fileCopy, source, destination);
При копировании большого файла интерфейс подвисает
.
2. Ладно, идём дальше, беру QThreadСначала делаю класс для копирования
filecopy.h
#ifndef FILECOPY_H
#define FILECOPY_H
#include <QObject>
class FileCopy : public QObject
{
Q_OBJECT
public:
FileCopy(const QStringList &files, const QString &path, QObject *parent = 0);
~FileCopy();
signals:
void finished();
private slots:
void process();
private:
QStringList filesList;
QString destination;
};
#endif // FILECOPY_H
filecopy.cpp
#include "filecopy.h"
#include <QFileInfo>
#include <QDir>
#include <QDebug>
FileCopy::FileCopy(const QStringList &files, const QString &path, QObject *parent)
: QObject(parent)
{
this->filesList = files;
this->destination = path;
}
FileCopy::~FileCopy()
{
}
void FileCopy::process()
{
foreach (QString file, filesList) {
QFileInfo file_info(file);
QString file_name = file_info.fileName();
QString destination_file = destination + QDir::separator() + file_name;
QFile::copy(file, destination_file);
emit finished();
}
}
Копируем:
QStringList file_list;
file_list << QDir::toNativeSeparators(url.toLocalFile());
QString copyToAddress = "\\Distrib"
QThread *thread = new QThread();
FileCopy *fileCopy = new FileCopy(file_list, copyToAddress);
fileCopy->moveToThread(thread);
connect(thread, SIGNAL(started()), fileCopy, SLOT(process()));
connect(fileCopy, SIGNAL(finished()), thread, SLOT(quit()));
connect(fileCopy, SIGNAL(finished()), fileCopy, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
Не помогло
3. Может виновата QFile::copy? Переписываю класс filecopy, избавляюсь от QFile::copyfilecopy.h
#ifndef FILECOPY_H
#define FILECOPY_H
#include <QObject>
class FileCopy : public QObject
{
Q_OBJECT
public:
explicit FileCopy(const QStringList &files, const QString &path, QObject *parent = 0);
~FileCopy();
signals:
void finished();
private slots:
void process();
private:
QStringList filesList;
QString destination;
quint64 bufferSize;
char *buffer;
};
#endif // FILECOPY_H
filecopy.cpp
#include "filecopy.h"
#include <QFileInfo>
#include <QDir>
#include <QDebug>
FileCopy::FileCopy(const QStringList &files, const QString &path, QObject *parent)
: filesList(files), destination(path), bufferSize(1024*512), QObject(parent)
{ }
FileCopy::~FileCopy()
{ }
void FileCopy::process()
{
foreach (QString file, filesList) {
QFileInfo fileInfo(file);
QString sFileName = fileInfo.fileName();
QString sDestinationFile = destination + QDir::separator() + sFileName;
int i = 1;
while (QFile::exists(sDestinationFile)) {
sFileName = fileInfo.fileName() + "_" + QString::number(i)
+ "." + fileInfo.suffix();
sDestinationFile = destination + QDir::separator() + sFileName;
i++;
}
QFile sourceFile(file);
QFile destinationFile(sDestinationFile);
if (!sourceFile.open(QIODevice::ReadOnly)) {
emit finished();
return;
}
if (!destinationFile.open(QIODevice::WriteOnly)) {
emit finished();
return;
}
quint64 fileSize = sourceFile.size();
if (!destinationFile.resize(fileSize)) {
emit finished();
return;
}
buffer = (char*)malloc(bufferSize);
if(!buffer) {
emit finished();
return;
}
quint64 position = 0;
while (position < fileSize) {
quint64 chunk = fileSize - position;
quint64 i = chunk > bufferSize ? bufferSize : chunk;
sourceFile.read(buffer, i);
destinationFile.write(buffer, i);
position += i;
sourceFile.seek(position);
destinationFile.seek(position);
}
emit finished();
}
}
В основной программе копирование не изменилось. Чтобы не ходить далеко, привожу ещё раз
QStringList file_list;
file_list << QDir::toNativeSeparators(url.toLocalFile());
QString copyToAddress = "\\Distrib"
QThread *thread = new QThread();
FileCopy *fileCopy = new FileCopy(file_list, copyToAddress);
fileCopy->moveToThread(thread);
connect(thread, SIGNAL(started()), fileCopy, SLOT(process()));
connect(fileCopy, SIGNAL(finished()), thread, SLOT(quit()));
connect(fileCopy, SIGNAL(finished()), fileCopy, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
Оно, конечно, теперь не виснет намертво на всё время копирования, но реагирует рывками - чем больше буффер, тем на большее время подвисает.