Russian Qt Forum
Ноябрь 25, 2024, 18:31
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Вопросы новичков
>
Многопоточность и виджеты: фундаментальный вопрос
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Многопоточность и виджеты: фундаментальный вопрос (Прочитано 5006 раз)
PinkPanther
Самовар
Offline
Сообщений: 169
Многопоточность и виджеты: фундаментальный вопрос
«
:
Февраль 28, 2015, 12:36 »
Добрый день. Встал фундаментальный вопрос, который не до конца понят, в силу недостаточного опыта программирования потоков.
У меня в приложении имеется QTabWidget, который, по необходимости, можно расширить некоторым количеством вкладок. Количество вкладок определяется пользователем при помощи QSpinBox, они создаются и добавляются в QTabWidget по нажатию кнопки (все сразу), а старт активности процессов на этих вкладках запускается другой кнопкой в общем окне. Потом, по необходимости, пользователь должен иметь возможность остановить процессы, удалить вкладки из QTabWidget, и начать все сначала.
На каждой вкладке есть QWebView, несколько текстовых полей (для лога, ввода URL и т.д.), и еще несколько управляющих элементов. Нужно сделать так, чтобы все виджеты вкладки, включая QWebView, работали в отдельном потоке вкладки. Также необходимо, чтобы все подключенные к виджетам слоты также работали в потоке своей вкладки.
Достаточно ли создать новый класс (например, MyTabMultiThread), унаследовав его от QTab и QThread, и добавив в него виджеты в качестве переменных?
Или виджеты, которые должны работать в потоке, необходимо создавать исключительно в функции run()?
Как насчет слотов, которые будут обслуживать события QWebView и других виджетов, принадлежащих вкладке? Как заставить слоты (а точнее, все методы дочернего класса) работать в отдельном потоке? Или следует создать для каждого типа виджеда дочерний класс, включить в него слоты обработки событий, а потом создать их экземпляры в run()? Возможно, имеет смысл создать дочерний класс лишь на базе QThread, а вкладку тоже создавать в run(), динамически, и хранить ее адрес в public-указателе дочернего класса?
Помогите пожалуйста разобраться.
«
Последнее редактирование: Февраль 28, 2015, 13:07 от PinkPanther
»
Записан
Эвтаназия - наше хобби!
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Многопоточность и виджеты: фундаментальный вопрос
«
Ответ #1 :
Февраль 28, 2015, 13:26 »
Цитата: PinkPanther от Февраль 28, 2015, 12:36
Или виджеты, которые должны работать в потоке, необходимо создавать исключительно в функции run()?
Виджеты (рисование UI) могут работать только в главной нитке. Вы можете рисовать в буферах (напр QImage) но вывод на экран - только в главной. Ну и делайте выводы
Записан
PinkPanther
Самовар
Offline
Сообщений: 169
Re: Многопоточность и виджеты: фундаментальный вопрос
«
Ответ #2 :
Февраль 28, 2015, 13:35 »
Цитата: Igors от Февраль 28, 2015, 13:26
Цитата: PinkPanther от Февраль 28, 2015, 12:36
Или виджеты, которые должны работать в потоке, необходимо создавать исключительно в функции run()?
Виджеты (рисование UI) могут работать только в главной нитке. Вы можете рисовать в буферах (напр QImage) но вывод на экран - только в главной. Ну и делайте выводы
А работа с сетью (QNetworkAccessManager)? А рендеринг HTML-страницы QWebView-ом? А код JavaScript, который выполняется на странице, а также Java и Flash?
Рисование виджетов не занимает много времени, пусть вывод на экран останется в главном потоке. А вот сетевые запросы, исполнение скриптов и рендеринг было бы желательно распараллелить.
Записан
Эвтаназия - наше хобби!
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Многопоточность и виджеты: фундаментальный вопрос
«
Ответ #3 :
Февраль 28, 2015, 14:27 »
Некоторые из Ваших тезисов
Цитата: PinkPanther от Февраль 28, 2015, 12:36
...создать новый класс (например, MyTabMultiThread), унаследовав его от QTab и QThread, и
...
Или виджеты, которые должны работать в потоке, необходимо создавать исключительно в функции run()?
Ну вот Вы создали виджет в "неглавной" нитке. Действия с ним вызовут события рисования которые полетят в EventLoop этой нитки. Но рисовать там нельзя - и что будете делать?
Цитата: PinkPanther от Февраль 28, 2015, 13:35
А вот сетевые запросы, исполнение скриптов и рендеринг было бы желательно распараллелить.
Так параллельте на здоровье, но без виджетов напрямую, общайтесь с ними через сигналы.
Записан
PinkPanther
Самовар
Offline
Сообщений: 169
Re: Многопоточность и виджеты: фундаментальный вопрос
«
Ответ #4 :
Февраль 28, 2015, 16:45 »
Цитата: Igors от Февраль 28, 2015, 14:27
Ну вот Вы создали виджет в "неглавной" нитке. Действия с ним вызовут события рисования которые полетят в EventLoop этой нитки. Но рисовать там нельзя - и что будете делать?
...
Так параллельте на здоровье, но без виджетов напрямую, общайтесь с ними через сигналы.
По п.1 понял, спасибо!
По п.2... QWebView общается с сетью при помощи QNetworkAccessManager, который, в свою очередь, встроен в QWebPage. QWebPage можно заменить на свой, и QNetworkAccessManager - тоже.
Если я создам в отдельном потоке объекты этих классов и встрою в QWebView, который живет в основном потоке, будет ли такая конструкция работать?
Если будет, то сразу же старый вопрос: как организовать обработку сигналов в разных потоках? Экземпляры должны создаваться в классе, который наследует QThread, или только в ф-ции run()? Обработчики сигналов, предположительно, будут зашиты в дочерний класс. Например, обработкой окончания загрузки Url будет заниматься метод класса, наследуемого от QNetworkAccessManager.
Записан
Эвтаназия - наше хобби!
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Многопоточность и виджеты: фундаментальный вопрос
«
Ответ #5 :
Февраль 28, 2015, 17:13 »
Про QNetworkAccessManager ничего не скажу, с ним не работал
Цитата: PinkPanther от Февраль 28, 2015, 16:45
Экземпляры должны создаваться в классе, который наследует QThread, или только в ф-ции run()?
Не проблема, т.к. с помощью moveToThread всегда можно сказать объекту в EventLoop какой нитки он будет принимать сигналы
Цитата: PinkPanther от Февраль 28, 2015, 16:45
Если будет, то сразу же старый вопрос: как организовать обработку сигналов в разных потоках?
Так там уже все организовано
См Qt::AutoConnection. Пример
Object1 принадлежит QThread1 и испускает сигнал для Object2. Если Object2 в др нитке (напр QThread2), то сигнал (фактически событие) будет помещен в очередь событий QThread2. По дефаулту метод QThread2::run запускает EventLoop, значит сигнал до него дойдет. Вам остается только пулять сигналами
Записан
PinkPanther
Самовар
Offline
Сообщений: 169
Re: Многопоточность и виджеты: фундаментальный вопрос
«
Ответ #6 :
Февраль 28, 2015, 20:29 »
Спасибо! Очень интересно.
Я пока плохо понял, что Вы написали, т.к. не до конца понимаю, как работают многозадачные ОС, т.к. основной опыт программирования набирался в 80-90 годы, под DOS и другие однозадачные OS.
Узкое место моего приложения - обработчик окончания загрузки страницы QWebView, так как в некоторых случаях приходится вступать в сложный диалог с интерфейсом, страница которого загружается. Интерфейс содержит массу JS-кода, в JS-коде используется AJAX, он отсылает введенные программой данные на сервер сервиса, потом меняет код HTML-страницы. С момента ввода до момента изменения страницы приходится ждать, потом реагировать и принимать новые решения. И так - в цикле, до 20 раз на одну загрузку. Это случается не постоянно, но случается. Когда виджетов станет больше, загрузки будут происходить чаще, и обработка должна идти параллельно, иначе теряется смысл объединения, а если параллелить в потоке главного процесса, то начнутся тормоза.
Сейчас у меня просто запущено 5 экземпляров приложения, с одним активным браузером в каждом. Они работают, но работать с 5 приложениями неудобно. Я хочу объединить несколько QWebView, чтобы было проще вести статистику и контролировать работу. Подскажите пожалуйста, как при помощи сигналов и слотов в Qt можно вывести обработчик "страница загружена" в отдельный поток, для каждого QWebView? В каком классе он должен находиться, чтобы QWebView мог его вызывать?
Изначально я хотел поместить каждый набор виджетов в отдельный QThread, там же объявить указатели на виджеты общего статистического окна, и менять текст в главном окне, по мере необходимости. Но раз QWebView не может работать в отдельном потоке...
Записан
Эвтаназия - наше хобби!
Igors
Джедай : наставник для всех
Offline
Сообщений: 11445
Re: Многопоточность и виджеты: фундаментальный вопрос
«
Ответ #7 :
Март 01, 2015, 10:27 »
Цитата: PinkPanther от Февраль 28, 2015, 20:29
Сейчас у меня просто запущено 5 экземпляров приложения, с одним активным браузером в каждом. Они работают, но работать с 5 приложениями неудобно. Я хочу объединить несколько QWebView, чтобы было проще вести статистику и контролировать работу. Подскажите пожалуйста, как при помощи сигналов и слотов в Qt можно вывести обработчик "страница загружена" в отдельный поток, для каждого QWebView? В каком классе он должен находиться, чтобы QWebView мог его вызывать?
Здесь не смогу помочь т.к. с QWebView не работал. Бегло глянув букварь: ну страницу от наверняка сам грузит в отдельном потоке, по завершении выдает сигнал loadFinished. Неясно зачем Вам еще создавать поток, и что будет делать тамошний обработчик. Но еще раз: пусть ответят те кто с этим работал.
Записан
PinkPanther
Самовар
Offline
Сообщений: 169
Re: Многопоточность и виджеты: фундаментальный вопрос
«
Ответ #8 :
Март 01, 2015, 17:19 »
Цитата: Igors от Март 01, 2015, 10:27
Цитата: PinkPanther от Февраль 28, 2015, 20:29
Сейчас у меня просто запущено 5 экземпляров приложения, с одним активным браузером в каждом. Они работают, но работать с 5 приложениями неудобно. Я хочу объединить несколько QWebView, чтобы было проще вести статистику и контролировать работу. Подскажите пожалуйста, как при помощи сигналов и слотов в Qt можно вывести обработчик "страница загружена" в отдельный поток, для каждого QWebView? В каком классе он должен находиться, чтобы QWebView мог его вызывать?
Здесь не смогу помочь т.к. с QWebView не работал. Бегло глянув букварь: ну страницу от наверняка сам грузит в отдельном потоке, по завершении выдает сигнал loadFinished. Неясно зачем Вам еще создавать поток, и что будет делать тамошний обработчик. Но еще раз: пусть ответят те кто с этим работал.
Не уверен, что обработка идет в отдельном потоке... Попытка повесить в окно несколько активных браузеров с обработчиками загружает приложение под завязку. Но что мешает написать обработчик, который при окончании загрузки лишь меняет переменную-флаг, а run() под каждый QWebView пасет изменение этого флага с интервалом 0.1 сек, в промежутках запуская QEventLoop?
В любом случае, спасибо за разъяснения. Узнал много полезного.
Записан
Эвтаназия - наше хобби!
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...