Russian Qt Forum
Ноябрь 23, 2024, 17:44 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QNetworkAccessManager и тишина после get()  (Прочитано 4909 раз)
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« : Июль 02, 2010, 10:25 »

Как то давно пытался реализовать на Qt удобное API для многопоточной закачки файлов по Http и Ftp, но как то со временем был кисляк, и сейчас опять взялся, в общем наткнулся на магию, после вызова метода get() класса QNetworkAccessManager полная тишина, ни один слот не вызывается, вот решил выложит код на суд гуру, конечно понимаю что сам где то накосячил, но что то не могу найти где. 

метод get() расположен в файлике http_download.cpp
Код:
void HttpDownloadSection::run()
{
    qDebug() << "Start thread download section";

    QNetworkRequest request;
    request.setUrl(download_url);

    manager = new QNetworkAccessManager(0);
    manager->moveToThread(this);
    connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(finished(QNetworkReply*)));

    reply = manager->get(QNetworkRequest(QUrl(download_url)));
    connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadProgress(qint64,qint64)));
    connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(errorDonload(QNetworkReply::NetworkError)));

    exec();
}
Записан
ufna
Гость
« Ответ #1 : Июль 02, 2010, 11:10 »

а как тестировать то прогу? В смысле какие агрументы?

больше всего похоже что мэнеджер и реплай - в разных потоках. Самое рабочее решение здесь отослать сигнал какой-нибудь, связанный со слотом, который начнет загрузку, а потом делать exec() - тогда все будет точно в одном потоке дальше, а то "до exec()" и "после exec()" - воспринимается разными потоками для этой хрени, я тут вчера имелся с многопоточной загрузкой на сервак как раз.
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #2 : Июль 02, 2010, 11:13 »

а как тестировать то прогу? В смысле какие агрументы?

Первый аргумент это url на файл а второй кол-во потоков

больше всего похоже что мэнеджер и реплай - в разных потоках. Самое рабочее решение здесь отослать сигнал какой-нибудь, связанный со слотом, который начнет загрузку, а потом делать exec() - тогда все будет точно в одном потоке дальше, а то "до exec()" и "после exec()" - воспринимается разными потоками для этой хрени, я тут вчера имелся с многопоточной загрузкой на сервак как раз.

вполне может быть, но даже если сделать просто
Код:
manager->get(QNetworkRequest(QUrl(download_url)));

то хотя бы finished должен был бы вызвать Непонимающий
Записан
ufna
Гость
« Ответ #3 : Июль 02, 2010, 11:33 »

Ну ты и намудрил с потоками, я тебе скажу.

Ошибка у тебя в том, что "части" ты создаешь в потоке "загрузка", и туда их тыкаешь, а поток "загрузка" у тебя в эвент луп не входит. Добавь exec() в HttpDownload::run() и данный пункт у тебя радостно заработает.
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #4 : Июль 02, 2010, 11:38 »

И то верно, перемудрил, спасибо заработало, как то упустил Улыбающийся
Записан
SimpleSunny
Гость
« Ответ #5 : Июль 02, 2010, 12:02 »

ТАм не только с потоками перемудрено Улыбающийся
Немного покритикую.

Что это за дивная контрукция?
Код
C++ (Qt)
int index = 0;
   for (index ; index < storage.size();)
   {
       if (storage[index].url == handle.url)
       {
           storage[index] = handle;
           break;
       } ++index;
 
       if (storage[index].url == handle.url)
       {
           storage[index] = handle;
           break;
       } ++index;
 
       if (storage[index].url == handle.url)
       {
           storage[index] = handle;
           break;
       } ++index;
 
       if (storage[index].url == handle.url)
       {
           storage[index] = handle;
           break;
       } ++index;
   }
 
Возможно подразумевалось такое?
Код
C++ (Qt)
int index;
   for (index = 0; index < storage.size(); ++index)
   {
       if (storage[index].url == handle.url)
       {
           storage[index] = handle;
           break;
       }
   }
 

Код
C++ (Qt)
if (storage[index].status != HandleFile::Error)
Следовало бы сделать проверку на коректность index (index < storage.size()).

Код
C++ (Qt)
           if ((i+1)*h_file.length > h_file.length)
           {
               listDownloadSection.append(new HttpDownloadSection(h_file.url,i*(h_file.length / h_file.count_thread ),
                                                                  h_file.length,h_file.accept_range,0));
               listDownloadSection[listDownloadSection.count()-1]->moveToThread(this);
               listDownloadSection[listDownloadSection.count()-1]->start();
           }
           else
           {
               listDownloadSection.append(new HttpDownloadSection(h_file.url,i*(h_file.length / h_file.count_thread ),
                                                              (i+1)*(h_file.length / h_file.count_thread ),h_file.accept_range,0));
               listDownloadSection[listDownloadSection.count()-1]->moveToThread(this);
               listDownloadSection[listDownloadSection.count()-1]->start();
           }
       }
 

Было б понятней, если бы выглядело так:
Код
C++ (Qt)
int size;
if ((i+1)*h_file.length > h_file.length)
   size = h_file.length;
else
   size = (i+1)*(h_file.length / h_file.count_thread );
 
listDownloadSection.append(new HttpDownloadSection(h_file.url,i*(h_file.length / h_file.count_thread ), size ,h_file.accept_range,0));
listDownloadSection.last()->moveToThread(this);
listDownloadSection.last()->start();
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #6 : Июль 02, 2010, 12:17 »

Немного покритикую.

Это всегда пожалуйста, критика это хорошо Улыбающийся

Что это за дивная контрукция?

если я не ошибаюсь, такой поиск осуществляется  в контейнерах stl , ибо сама по себе одна итерация for это довольно долгая операция ,а сравнение работает гораздо быстрее , то в этом случае поиск будет проходить быстрее, этот код поиска я чуть позже вынесу в отдельную ф-цию и буду передавать возвращаемое значение по ссылке.

Следовало бы сделать проверку на коректность index (index < storage.size()).

возможно, но я не могу представить себе ситуацию когда index будет больше чем storage.size() ибо при инициализации  он равен нулю, а в цикле заданно
Код:
index < storage.size()

и index используется только внутри этой ф-ции, это же не глобальная переменная

Было б понятней, если бы выглядело так:

с этим согласен, действительно было бы понятнее Улыбающийся
Записан
SimpleSunny
Гость
« Ответ #7 : Июль 02, 2010, 13:26 »

если я не ошибаюсь, такой поиск осуществляется  в контейнерах stl , ибо сама по себе одна итерация for это довольно долгая операция ,а сравнение работает гораздо быстрее , то в этом случае поиск будет проходить быстрее, этот код поиска я чуть позже вынесу в отдельную ф-цию и буду передавать возвращаемое значение по ссылке.
Преждевременная оптимизация - зло Улыбающийся
Такой подход был бы оправдан, если бы количество итераций было бы задано заранее и это место было бы узким в роботе программы. А так получаем плохо читаемый код к тому же с ошибкой, так как нет гарантий, что где-то в середине тела цикла index не превысит storage.size() - 1.
К тому же компиляторы и сами хорошо умеют частино разворачивать циклы для повышения бытсродействия.
В контейнерах stl используются итераторы и конструкции наподобии такого
Код
C++ (Qt)
while (__first != __last && !(*__first == __val))
   ++__first;
return __first;

возможно, но я не могу представить себе ситуацию когда index будет больше чем storage.size() ибо при инициализации  он равен нулю, а в цикле заданно
Код:
index < storage.size()
и index используется только внутри этой ф-ции, это же не глобальная переменная
Когда поиск не увенчался успехом. index=storage.size();
Записан
ecspertiza
Супер
******
Offline Offline

Сообщений: 1053


С уважением, мастер конфетного цеха!


Просмотр профиля
« Ответ #8 : Июль 02, 2010, 13:31 »

Преждевременная оптимизация - зло
Такой подход был бы оправдан, если бы количество итераций было бы задано заранее и это место было бы узким в роботе программы. А так получаем плохо читаемый код к тому же с ошибкой, так как нет гарантий, что где-то в середине тела цикла index не превысит storage.size() - 1.
К тому же компиляторы и сами хорошо умеют частино разворачивать циклы для повышения бытсродействия.

согласен, пожалуй поправлю Улыбающийся

Когда поиск не увенчался успехом. index=storage.size();

Про это уже подумал, и добавил проверку Улыбающийся

Если будет еще критика, то пишите, критика тем более здравая на мой взгляд никогда лишней не бывает Улыбающийся

P.S. Убивает как на этом движке реализована кнопка "Цитата"  Улыбающийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.152 секунд. Запросов: 22.