Название: Асинхронное копирование файлов вешает интерфейс
Отправлено: gladsky от Июнь 06, 2017, 13:03
Копирование большого файла в основном потоке приложения замораживает его интерфейс. Копирование в отдельном потоке не помогает. Подскажите, пожалуйста, почему интерфейс всё равно замерзает. 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();
Оно, конечно, теперь не виснет намертво на всё время копирования, но реагирует рывками - чем больше буффер, тем на большее время подвисает.
Название: Re: Асинхронное копирование файлов вешает и
Отправлено: Пантер от Июнь 06, 2017, 13:17
Странно, первый и второй способы корректны. А у тебя случаем не фризится вся система?
Название: Re: Асинхронное копирование файлов вешает интерфейс
Отправлено: Пантер от Июнь 06, 2017, 13:27
И еще вопрос - ты привел полный код или упростил его, удалив ненужное? Может, проблема в том коде, который ты не приводишь? Допустим, пытаешься GUI дергать внутри функции копирования.
Название: Re: Асинхронное копирование файлов вешает интерфейс
Отправлено: gladsky от Июнь 06, 2017, 14:03
И еще вопрос - ты привел полный код или упростил его, удалив ненужное? Может, проблема в том коде, который ты не приводишь? Допустим, пытаешься GUI дергать внутри функции копирования.
Система не подвисает. Код только копирует файлы, больше ничего ещё не навесил. Если заменить копирование на что-нибудь простое, типа как код ниже, то отрабатывает нормально, интерфейс не фризится. for (int i = 0; i < 100; i++) { qDebug() << i; Sleep(uint(5000)); }
Название: Re: Асинхронное копирование файлов вешает интерфейс
Отправлено: Пантер от Июнь 06, 2017, 14:14
А под замораживанием интерфейса ты что понимаешь? Я писал свой ФМ, проблем таких не возникало.
Название: Re: Асинхронное копирование файлов вешает интерфейс
Отправлено: qate от Июнь 07, 2017, 08:18
сделал бы минимальный проект, можно было бы посмотреть а разбираться в портянках кода и копипастить их откровенно лень
Название: Re: Асинхронное копирование файлов вешает интерфейс
Отправлено: Авварон от Июнь 07, 2017, 13:21
+1, первый способ должен рабоатть. Случаем, футуру нигде не ждут?
|