Russian Qt Forum

Qt => Вопросы новичков => Тема начата: momo11 от Январь 13, 2014, 10:50



Название: QNetworkAccessManager и QThread
Отправлено: momo11 от Январь 13, 2014, 10:50
Сделал класс который в несколько потоков запрашивает страницу и результат выводит в qDebug.
хэдер:
Код:
#ifndef CHECK_H
#define CHECK_H
#include <QMainWindow>
#include <QDebug>
#include <QMessageBox>
#include <QtNetwork/QNetworkAccessManager>
#include <QUrl>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QThread>

class Check : public QThread
{
public:
    Check(QObject *parent = 0) : QThread(parent) {}
    virtual void run();

private slots:
        void end(QNetworkReply*);

private:
    QNetworkAccessManager *Mgr;

};

#endif // CHECK_H

Сам файл
Код:
#include "check.h"

Check::run()
{
    qDebug()<<"runn";
    QNetworkAccessManager *Mgr = new QNetworkAccessManager(this);
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(end(QNetworkReply*)));
    manager->get(QNetworkRequest(QUrl("http://site.com")));
}

Check::end(QNetworkReply* reply)
{
    qDebug()<<reply->readAll();
}

Ошибки:
Код:
D:\QT\Tools\QtCreator\bin\myprog\check.cpp:3: ошибка: ISO C++ forbids declaration of 'run' with no type [-fpermissive]
 Check::run()
            D:\QT\Tools\QtCreator\bin\myprog\check.cpp:3: ошибка: prototype for 'int Check::run()' does not match any in class 'Check'
 Check::run()
 ^
D:\QT\Tools\QtCreator\bin\myprog\check.cpp:1: In file included from ..\myprog\check.cpp:1:0:
D:\QT\Tools\QtCreator\bin\myprog\check.h:16: ошибка: candidate is: virtual void Check::run()
     virtual void run();
                  ^
D:\QT\Tools\QtCreator\bin\myprog\check.cpp:11: ошибка: ISO C++ forbids declaration of 'end' with no type [-fpermissive]
 Check::end(QNetworkReply* reply)
                                ^
D:\QT\Tools\QtCreator\bin\myprog\check.cpp:11: ошибка: prototype for 'int Check::end(QNetworkReply*)' does not match any in class 'Check'
 Check::end(QNetworkReply* reply)
 ^
D:\QT\Tools\QtCreator\bin\myprog\check.cpp:1: In file included from ..\myprog\check.cpp:1:0:
D:\QT\Tools\QtCreator\bin\myprog\check.h:19: ошибка: candidate is: void Check::end(QNetworkReply*)
         void end(QNetworkReply*);
              ^


Название: Re: QNetworkAccessManager и QThread
Отправлено: Serr500 от Январь 13, 2014, 11:16
void перед run и end в реализации кто будет указывать? Если нет ничего, предполагается int и сейчас так вообще не принято и большинство компиляторов по умолчанию это считает ошибкой.


Название: Re: QNetworkAccessManager и QThread
Отправлено: momo11 от Январь 13, 2014, 12:41
Точно, исправил, но теперь программа крашится при запуске потока.
Запускаю так:
Код:
 Check asd;
    asd.start();

и ошибки в выводе приложения:
Код:
QThread: Destroyed while thread is still running
QMutex: destroying locked mutex
Программа неожиданно завершилась.


Название: Re: QNetworkAccessManager и QThread
Отправлено: Serr500 от Январь 13, 2014, 12:59
Похоже, документацию по QThread Вы вообще не читали.

1) Как только завершился run, ваш потомок QThread остановит работу и ничего больше выполняться там не будет.
2) Переменная типа Check у Вас где-то в стеке функции и разрушается при выходе из этой функции.
3) Зачем Вам поток? QNAM сам по себе асинхронный.


Название: Re: QNetworkAccessManager и QThread
Отправлено: momo11 от Январь 13, 2014, 13:26
значит run завершается, а из run'a у меня идет сигнал  connect(Mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(end(QNetworkReply*))); , как сделать чтобы run не завершался а ждал пока сигнал на сработает?
может быть создать бесконечный цикл который будет проверять записался ли в переменную исходный код страницы, если нет то ожидать и снова проверять


Название: Re: QNetworkAccessManager и QThread
Отправлено: momo11 от Январь 13, 2014, 13:32
или может у thread'ов есть какое нибудь свойство, которое не дает завершить поток пока все сигналы не сработали


Название: Re: QNetworkAccessManager и QThread
Отправлено: Serr500 от Январь 13, 2014, 15:05
значит run завершается, а из run'a у меня идет сигнал  connect(Mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(end(QNetworkReply*)));
Сигнал идёт не из run'а. Сигнал идёт от QNAM, а в run он просто соединяется со слотом. Сигнал почти наверняка пойдёт уже после выхода из run.

как сделать чтобы run не завершался а ждал пока сигнал на сработает?
Например, в конце run вызвать exec. Тогда event loop потока будет крутиться, пока ему не вызовут quit (или terminate).

может быть создать бесконечный цикл который будет проверять записался ли в переменную исходный код страницы, если нет то ожидать и снова проверять
Это решение уровня DOS 5.0.  ;D

или может у thread'ов есть какое нибудь свойство, которое не дает завершить поток пока все сигналы не сработали
Нет.


Название: Re: QNetworkAccessManager и QThread
Отправлено: momo11 от Январь 13, 2014, 16:07
уже прогресс небольшой, вот методы класса который выполняется в потоке
Код:
void Check::run()
{
    qDebug()<<"runn";
    QNetworkAccessManager *Mgr = new QNetworkAccessManager(this);
    connect(Mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(end(QNetworkReply*)));
    Mgr->get(QNetworkRequest(QUrl("http://wapos.ru")));
    exec();
}

void Check::end(QNetworkReply* reply)
{
    qDebug()<<reply->readAll();
    quit();
}
runn выводится, а вот далее идут ошибки
Код:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QThread(0x22fe40), parent's thread is QThread(0x12bdcc0), current thread is QThread(0x22fe40)
QObject::connect: No such slot QThread::end(QNetworkReply*)
QThread: Destroyed while thread is still running

вызываю так
Код:
    asd.start();
asd создана как глобальная переменная, чтобы не дохла после нажатия кнопки


Название: Re: QNetworkAccessManager и QThread
Отправлено: Serr500 от Январь 13, 2014, 16:37
Код:
QNetworkAccessManager *Mgr = new QNetworkAccessManager();
Mgr->moveToThread(this);


Название: Re: QNetworkAccessManager и QThread
Отправлено: momo11 от Январь 13, 2014, 16:59
может я чего то не догоняю, но помоему ничего не изменилось, те же ошибки


Название: Re: QNetworkAccessManager и QThread
Отправлено: Serr500 от Январь 13, 2014, 20:09
Выложите весь проект, будем посмотреть, по кускам непонятно.


Название: Re: QNetworkAccessManager и QThread
Отправлено: Old от Январь 13, 2014, 20:22
может я чего то не догоняю, но помоему ничего не изменилось, те же ошибки
Самое простое не передавать parent в конструктор QNetworkAccessManager (убрать this), но нужно будет не забывать самому его удалять.
Лучше сделать так:
Код
C++ (Qt)
void Check::run()
{
   qDebug()<<"runn";
   QNetworkAccessManager Mgr;
   connect( &Mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(end(QNetworkReply*)));
   Mgr.get(QNetworkRequest(QUrl("http://wapos.ru")));
   exec();
}