2016-11-05 9 views
0

я использовал пример, как док http://doc.qt.io/qt-4.8/qnetworkaccessmanager.htmlСкачать большие файлы с QNetworkReply :: ReadAll замерзает в течение нескольких секунд

я создаю startDownload:

connect(pushButton, SIGNAL(clicked(bool)), this, SLOT(startDownload(bool))); 

В startDownload(bool) я поставил этот:

file = new QFile("C:/foo/bar/bigfile.7z"); 
file->open(QIODevice::WriteOnly); 

QNetworkRequest request; 
request.setUrl(QUrl("http://localhost/bigfile.7z")); 
request.setRawHeader("User-Agent", "MyOwnBrowser 1.0"); 

QNetworkReply *reply = manager->get(request); 

connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); 
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), 
     this, SLOT(slotError(QNetworkReply::NetworkError))); 
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), 
     this, SLOT(slotSslErrors(QList<QSslError>))); 

В slotReadyRead Я положил это:

file->write(reply->readAll()); 

Но когда загрузка заканчивается, происходит небольшое замораживание 2 секунд, а затем возвращается в нормальное состояние и загрузка завершена. Эта проблема возникает только в том случае, если файл, который я пытаюсь передать, большой.

+0

Я попытался написать [минимальный пример] (http://pastebin.com/et94k1Uk) для вашей проблемы. Я вычислил время для каждого 'file-> write (reply-> readAll())' call, большинство вызовов заняло 0 мс, последний вызов (в конце загрузки) не имел существенной разницы, поскольку вы описываете (Я пробовал код с локальным файлом в моей сети размером около 1 ГБ). Может быть, это другое дело в вашем коде, что замедляет работу?попробуйте измерить длительность вызовов функций, чтобы убедиться, что это действительно этот вызов, который вызывает проблему. – Mike

+0

@Mike проблема возникает только в приложениях GUI, например, с 'QMainWindow' –

+0

Проблема возникает в графическом интерфейсе, потому что обратный вызов занимал * много * времени для завершения и возвращался обратно в цикл событий. В своем тесте я просто измеряю количество времени, затраченного на 'file-> write (reply-> readAll());' чтобы убедиться, что на самом деле это занимает 2 секунды в конце загрузки. Но оказалось, что на самом деле это не так долго, а выход отличается от вашего? – Mike

ответ

1

После попытался кода использовать @ Mike, я заметил, что данные, считываемые в readyRead финале намного выше, чем предыдущий, что делает его медленно писать в файл:

without setReadBufferSize

Последние два показания:

  1. 46080000 байт - требуется ~ 1,6 секунды для записи.
  2. 227323951 байт - требуется ~ 2,7 секунды для записи.

Это варьируется в зависимости от типа сети и скорости, позволяя буфер, чтобы быть большим или нет.

В приложениях с графическим интерфейсом вызывают чувство «замораживания» в течение ~ 4 секунд.

Для LIMITE буфера я использовал QNetworkReply::setReadBufferSize, увидеть разницу:

with setReadBufferSize

чтение было в 1048576 байт - занимает от 2 до 10 мсек, чтобы писать.

+0

@KubaOber Я понимаю, но это было единственное, что сработало, я следил за руководством '@ ddriver' , ты мог бы показать мне лучший способ? –

+0

Вы протекаете экземпляр диспетчера сетевого доступа. Поскольку загрузчику всегда нужен диспетчер сетевого доступа, вы можете добавить его в качестве члена и удерживать его по значению, нет необходимости его воссоздавать каждый раз при вызове 'process()'. –

+0

В какой-то момент я дам еще один ответ :) –

2

Это ожидаемое поведение. QIODevice::readAll() заблокирует поток до завершения загрузки. Возможно, QFile::write() также может блокироваться в зависимости от скорости диска и политики кэширования. Метод readAll() может также потреблять довольно много ОЗУ, если файл достаточно большой.

Самое простое решение - загрузить файл в более мелкие куски, используя read() вместо readAll().

Теперь, когда сказано, нет простого способа найти идеальный размер буфера для чтения из сети и записи на диск; это будет зависеть от того, как сетевое соединение реагирует на скорость записи на диск.

+0

Это имеет смысл, может привести пример? Благодаря! –

+0

Или если вы хотите использовать блокировку api, не блокируйте основной поток - используйте рабочий поток. – dtech

+0

@ddriver Спасибо, но я попытался использовать поток и даже задал еще один вопрос, я получил несколько близких голосов и downvotes и много reclameções в комментариях, которые не имели смысла, я удалил вопрос. –

 Смежные вопросы

  • Нет связанных вопросов^_^