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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QNetworkAccessManager & QThreads  (Прочитано 13698 раз)
BloodyTux
Гость
« : Октябрь 23, 2010, 19:24 »

Доброго времени суток!

Мне необходимо сделать многопоточное приложение, отправляющее http запросы. Естественно логично было бы использовать QNetworkAccessManager, но вот незадача:  когда запускаю в одном потоке, работает стабильно, при большем количестве - вылетают ошибки связанные с QMutex::lock(). Код:
Код:


/ ************** main.cpp **************** /


#include <QtCore/QCoreApplication>
#include <QDebug>
#include "threadhttpdownload.h"

#define USAGE QT_TRANSLATE_NOOP("threadDownload::main", "usage: %s <link> <file name>")

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        qDebug(USAGE, argv[0]);
        return 0;
    }

    QCoreApplication a(argc, argv);

    for (int i = 0; i < 5; i++) {
        ThreadHttpDownload *th = new ThreadHttpDownload(0,argv[1]);
        th->start();
        qDebug() << "tread " << i << " started";

    }

    return a.exec();
}



/ ************** threadhttpdownload.h **************** /



#ifndef THREADHTTPDOWNLOAD_H
#define THREADHTTPDOWNLOAD_H

#include <QThread>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QFile>
#include <QDebug>

class ThreadHttpDownload : public QThread
{
    Q_OBJECT

    public:
        ThreadHttpDownload(QObject *parent,QString link);

        void run();

    private:

        QString link;

    private slots:
        void replyFinished(QNetworkReply*);
};

#endif // THREADHTTPDOWNLOAD_H



/ ************** threadhttpdownload.h **************** /



#include "threadhttpdownload.h"

ThreadHttpDownload::ThreadHttpDownload(QObject *parent,QString _link)
        :QThread(parent)
{
     link = _link;

}

void ThreadHttpDownload::run()
{
   // qDebug() << currentThreadId();

    QNetworkAccessManager manager;

    connect(&manager, SIGNAL(finished(QNetworkReply*)),
             this, SLOT(replyFinished(QNetworkReply*)), Qt::DirectConnection);

    manager.get(QNetworkRequest(QUrl(link)));

    exec();
}


void ThreadHttpDownload::replyFinished(QNetworkReply *reply)
{
    // qDebug() << currentThreadId();

    if (reply->error())
    {
        qDebug() << "error download" << reply->errorString();
    }else
    {
        reply->readAll();
        qDebug() << "download complete";
    }
}


Варианты вывода :
Цитировать
tread  0  started
tread  1  started
tread  2  started
tread  3  started
tread  4  started
QMutex::lock: mutex lock failure: Недопустимый аргумент
download complete
download complete
download complete
download complete
download complete

Цитировать
tread  0  started
tread  1  started
tread  2  started
tread  3  started
tread  4  started
Ошибка сегментирования


replyFinished(QNetworkReply *reply) выполняется в рабочем потоке - проверял. Не могу понять, в чем дело... Да, проблема возникает и на linux и на win. QTcpSocket конечно работает, но как-то не хочется иметь дело с примитивами. Улыбающийся
Записан
GNU Dimarik
Гость
« Ответ #1 : Октябрь 24, 2010, 17:48 »

Я вообще не понял в чем проблема... Давайте сюда код с мютексами.
Записан
BloodyTux
Гость
« Ответ #2 : Октябрь 25, 2010, 17:11 »

Все, спасибо. Решил проблему.
Записан
ufna
Гость
« Ответ #3 : Октябрь 25, 2010, 20:47 »

А в чем была проблема?
Записан
AlekseyK
Гость
« Ответ #4 : Октябрь 26, 2010, 01:26 »

Все, спасибо. Решил проблему.
Обычно люди помещают решение и код, если проблема решена, чтобы тем, кто идёт следом было полегче.
Записан
BloodyTux
Гость
« Ответ #5 : Октябрь 26, 2010, 17:14 »

Дело в том, что решение, так сказать, радикальное. Решил отказаться от Qt для разработки данного проекта. Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #6 : Октябрь 26, 2010, 17:39 »

Мда... Вообще стоило сначала почитать про thread-safety и reentrant:)
Записан
Sahab
Гость
« Ответ #7 : Октябрь 27, 2010, 09:40 »

на сокетах Беркли решил написать?))
Записан
AlekseyK
Гость
« Ответ #8 : Октябрь 27, 2010, 12:03 »

Мда... Вообще стоило сначала почитать про thread-safety и reentrant:)
Я вот почитал - мне не помогло, у меня схожая проблема: http://www.prog.org.ru/topic_15421_0.html
Записан
ufna
Гость
« Ответ #9 : Октябрь 27, 2010, 12:35 »

Я сделал у себя немного по-другому, главное отличие касается run() функции, т.к. там есть "непонятки" с потоком-родителем и т.п.

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

подрихтовал и опубликовал здесь: http://ufna.ru/2010/10/27/qt-qnetworkaccessmanager-multithread
« Последнее редактирование: Октябрь 27, 2010, 13:30 от ufna » Записан
AlekseyK
Гость
« Ответ #10 : Октябрь 27, 2010, 12:43 »

Честно говоря не понял, что нужно изменить: у меня по принципу код похожий. Но ошибка вываливается, только, если закрыть программу во время загрузки страницы. Если позже - ошибка не возникает. Может QByteArray долго передаётся - не знаю (не понятно):
Код
C++ (Qt)
141: emit pageContentReady(pageContent, pageAddress);
Записан
ufna
Гость
« Ответ #11 : Октябрь 27, 2010, 13:43 »

он падает в любой момент при закрытии лично у меня

ошибка скорее всего в том, что менеджеру кто-то после этого шлет сигналы, а его уже нет. Суровое удаление через delete тут рисованно.

я бы на твоем месте сделал просто manager->setParent(this); после того как заслал его в this поток.
Записан
AlekseyK
Гость
« Ответ #12 : Октябрь 27, 2010, 14:11 »

Да, успешно, работает, спасибо. Теперь проверить нет ли утечек памяти.
Записан
ufna
Гость
« Ответ #13 : Октябрь 27, 2010, 14:18 »

"По идее" - быть не должно, поток-родитель подтереть должен. На практике - класс умирает вместе с приложением, висеть ничего не остается, потому в любом случае не критично.
Записан
AlekseyK
Гость
« Ответ #14 : Октябрь 27, 2010, 14:33 »

По идее - да, пробежался valgrind-ом на всякий случай - в этом компоненте их нет. Огромное спасибо!!!
« Последнее редактирование: Октябрь 27, 2010, 14:42 от AlekseyK » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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