Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Надёжность сигналов-слотов

5.7K
18 октября 2011 года
Lindemann66
193 / / 21.07.2011
Всем привет!

Представьте
Программа, выполняющая сканирование сайтов на предмет обновлений
Допустим, в БД 50 сайтов = 50 сканирующих "потоков"...
В каждом "потоке" - скачка html-кода из интернета, парсинг, внесение в БД...

Я специально закавычил слово "поток", потому что, в данном случае, использование потоков не обязательно...

Важно другое

Как организовать такую работу наиболее правильным "архитектурно-технологически" способом?
Мне просто интересны варианты :)

Уже пробовал создавать отдельный поток под каждый сайт, но проблема в том, что сканирование сайтов (читай - использование QWebPage) необходимо делать в главном (GUI) потоке
К тому же, этот механизм не показал особой стабильности...
Может, из-за корявости реализации, не использования QthreadPool'ов (ксттаи, интересно, насколько хорош QThreadPool))

Сейчас делаю так...(просто пример, но суть работы та же, что и в программе)
Analyzer
Код:
class Analyzer : public QObject {
    Q_OBJECT
public:
    Analyzer();
    ~Analyzer();
public slots:
    void analyze(QString str);
private:
    QList<Timer *> m_timers;
};

Analyzer::Analyzer() {
    //запускаем 100 таймеров
    for (int i = 0; i < 100; i++) {
        Timer *timer = new Timer(10000, i);
        m_timers.push_back(timer);
        connect(timer, SIGNAL(analyze(QString)),
                this, SLOT(analyze(QString))
                );
    }
}

Analyzer::~Analyzer() {
    for (int i = 0; i < m_timers.size(); i++) {
        delete m_timers;
    }
}

void Analyzer::analyze(QString str) {
    qDebug() << "Timer " + str;
}


Timer
Код:
class Timer : public QObject {
    Q_OBJECT
public:
    Timer(int interval, int number);
    ~Timer();

public slots:
    void needAnalyze();

signals:
    void analyze(QString str);

private:
    int m_number;
    QTimer *m_timer;
};
Timer::Timer(int interval, int number) {
    m_timer = new QTimer(this);
    //раз в 10 секунд
    m_timer->start(interval);

    connect(m_timer, SIGNAL(timeout()),
            this,    SLOT(needAnalyze())
            );

    m_number = number;
}

Timer::~Timer() {
    m_timer->stop();
    delete m_timer;
}

void Timer::needAnalyze() {
    emit analyze(QString::number(m_number));
}


То есть, есть класс анализатора, в котором создаются потоки, и каждый из них вызывает через определённое время сигнал о том, что необходимо произвести анализ
То есть, всё построено на механизме сигналов-слотов

Но, при "большом" объёме сайтов (примерно 20-30) - прога заваливается, и либо не сканирует какие-то сайты, либо не работает вообще

И я не могу определить, в чём тут проблема!
То есть, если брать 5 +-5 сайтов, то работа стабильна, а чуть больше - глючит
Дело ли тут в том, что механизм сигналов-слотов даёт сбой, или где-то в алгоритме ошибка (но прога ведь не падает..)?

Отсюда вопросы:
1. Насколько надёжно, на Ваш взгляд, использование механизма сигналов-слотов
2. Насколько оно надёжно в приведённом случае
3. Насколько рнационален, на Ваш взгляд, предложенный мной подход к решению проблемы
4. Ну и вообще, Ваше мнение на сей счёт

Вопросов много накатал...
Буду рад, если кто-нибудь ответит :)
277
18 октября 2011 года
arrjj
1.7K / / 26.01.2011
В одном потоке сигналы/слоты будут обрабатываться по очереди. Если боишься вручную парсить страничку - тогда к вебпежу на loadFinished слоты обработки коннекть, а там как у тебя религия позволит.
5.7K
18 октября 2011 года
Lindemann66
193 / / 21.07.2011
Эх...
разбить бы на потоки, да вопрос, что там проводить...
Если QWebPage должна быть в GUI!
GUI ведь только в главном потоке, в других не может быть?
277
18 октября 2011 года
arrjj
1.7K / / 26.01.2011
Цитата: Lindemann66
разбить бы на потоки, да вопрос, что там проводить...


Ну это не к нам а к тебе вопрос - мы то хз что ты там делаешь.

5.7K
18 октября 2011 года
Lindemann66
193 / / 21.07.2011
Цитата: arrjj
Ну это не к нам а к тебе вопрос - мы то хз что ты там делаешь.



агаа )

14
19 октября 2011 года
Phodopus
3.3K / / 19.06.2008
вообще понятия "главный поток" существовать не должно на этом уровне. и гуи должно-мочь-быть в любом потоке
277
19 октября 2011 года
arrjj
1.7K / / 26.01.2011
Цитата: Phodopus
вообще понятия "главный поток" существовать не должно на этом уровне. и гуи должно-мочь-быть в любом потоке



В Qt события окнам доставляются только в потоке, в котором QApplication::exec выполнен (говорят это должно быть только в main потоке).
QApplication::exec()
Qt Threads Basics говорит:

Цитата:

GUI Thread and Worker Thread

As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads. A secondary thread is commonly referred to as a "worker thread" because it is used to offload processing work from the main thread.

260
19 октября 2011 года
Ramon
1.1K / / 16.08.2003
1. У вас скорее сетевое взаимодействие должно оставаться в основном потоке и эта "радость" от тролей доступна только под вынем, чтобы не расслаблялись, а где и как вы обрабатываете результат это уже иное дело.
2. Таймеры, сколько бы вы их не завели, живут все в том же одном потоке и исполняются последовательно.
3. Перед использованием пула потоков необходимо осознать его предназначение.
14
19 октября 2011 года
Phodopus
3.3K / / 19.06.2008
Цитата: arrjj
В Qt события окнам доставляются только в потоке, в котором QApplication::exec выполнен (говорят это должно быть только в main потоке).
QApplication::exec()
Qt Threads Basics говорит:


Думаю все же что будет работать, пусть и в одном но "вторичном" потоке. Естестенно вся инициализация и exec должны быть в нем, коли множественные GUI Threads не поддерживаются. Да только тогда это всякий смысл теряет.

260
19 октября 2011 года
Ramon
1.1K / / 16.08.2003
Цитата: Phodopus
Думаю все же что будет работать, пусть и в одном но "вторичном" потоке. Естестенно вся инициализация и exec должны быть в нем, коли множественные GUI Threads не поддерживаются. Да только тогда это всякий смысл теряет.


А кто отменил асинхронный ввод/вывод и когда?

14
19 октября 2011 года
Phodopus
3.3K / / 19.06.2008
Цитата: Ramon
А кто отменил асинхронный ввод/вывод и когда?


Тут я только про Qt GUI, так что я не очень тебя понял

260
20 октября 2011 года
Ramon
1.1K / / 16.08.2003
Цитата: Phodopus
Тут я только про Qt GUI, так что я не очень тебя понял


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

PS: Наму амида буцу.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог