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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Длительные операции + QtConcurrent  (Прочитано 8486 раз)
Nidxogg
Гость
« : Сентябрь 23, 2014, 18:17 »

Добрый день.

Есть gui-программа, работающая с БД. Все запросы и т.д вынесены в отдельный класс.
Все работает в одном потоке.

Есть такой псевдокод, который должен выполнится строго в заданной последовательности.
Код:
void MyClass::myMethod()
{
    func1();
    func2();
    func3();
}

Собственно func2() выполняется довольно долго, поэтому решил на время фриза интерфейса добавить гифку-прогрессбар(+QMovie) .
Гифка, естественно, не анимируется в процессе выполнения func2(). processEvent() не помог.

Тогда решил выполнить func2() в отдельном потоке с использованием QtConcurrent::run(...), гифка ожила, но теперь func3() начинает выполняться до окончания func2();
Пробовал использовать waitForFinished, но опять столкнулся с фризом интерфейса.

Может у кого-нибудь есть идеи как выйти из ситуации?

Записан
Bepec
Гость
« Ответ #1 : Сентябрь 23, 2014, 18:22 »

Видимо вы как то не так делали processEvents Улыбающийся Всё должно работать без фризов.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #2 : Сентябрь 23, 2014, 18:23 »

Запускайте func3 в слоте, который будет вызываться при завершении потока, выполняющего func2.
Записан
Nidxogg
Гость
« Ответ #3 : Сентябрь 23, 2014, 18:44 »

Цитировать
Запускайте func3 в слоте, который будет вызываться при завершении потока, выполняющего func2.
Вы имеет ввиду соединить сигнал finished() от QFutureWatcher со слотом, и вызывать func3() там?

прим.: мне приходит несколько пакетов по сети практически одновременно, которые необходимо обработать.
В слоте я вызываю myMethod и рассчитываю, что обработка следующего пакета не начнется, пока не завершится обработка текущего (собственно так и работает, т.к все в одном потоке(если без QtConcurent)).  
Не получился ли, что я вызову myMethod раньше, чем завершится выполнение func3()?


Цитировать
Видимо вы как то не так делали processEvents Всё должно работать без фризов.
У меня прозрачный виджет ставится, аналог вашего sbglass (qlightboxwidget в гугле), на который кидается QLabel и гифка.
processEvents вызываю qApp->processEvents() во время обработки запроса из БД  (Порядка 150 раз в течение ~5 секунд);
« Последнее редактирование: Сентябрь 23, 2014, 18:48 от Nidxogg » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Сентябрь 23, 2014, 18:52 »

Гифка, естественно, не анимируется в процессе выполнения func2(). processEvent() не помог.
Не вижу здесь ничего естественного, надо разбираться. Вообще запуск потока только с целью обеспечить индикатор не есть хорошо/грамотно.
Записан
Nidxogg
Гость
« Ответ #5 : Сентябрь 23, 2014, 19:25 »

Цитировать
Не вижу здесь ничего естественного, надо разбираться
Главный поток загружен операциями в func2, интерфейс зафрижен.
Что не так?
Записан
Bepec
Гость
« Ответ #6 : Сентябрь 23, 2014, 20:58 »

Не так, что достаточно 25 раз в секунду вызывать processEvents чтобы пользователь вообще ничего не заподозрил.
Значит вы его вызываете или не там, или не так Улыбающийся

Т.е. вот такое высказывание верно:
Главный поток загружен операциями в func2, где вызывается processEvents, интерфейс работает нормально.
Записан
VPS
Гость
« Ответ #7 : Сентябрь 23, 2014, 22:58 »

Что Вам мешает все три метода обработки данных запускать последовательно в отдельном потоке, а принимаемые пакеты из главного (GUI или другого) потока передавать туда на обработку? В данном случае, для передачи пакетов, можно попробовать использовать сигналы или библиотеку, в которой есть потокобезопасная очередь. Т.е. получится что-то типа шаблона Producer-Consumer.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Сентябрь 24, 2014, 06:19 »

Главный поток загружен операциями в func2, интерфейс зафрижен.
Что не так?
А что "так"? Улыбающийся То что есть интенсивный расчет - еще не основание выносить его в отдельный поток. Вот напр если 2 расчета параллельно - тогда да. А так гораздо проще вызывать processEvents в теле расчета. 25 раз в сек - ну это для видео, а для UI достаточно и 5 раз. Попробуйте вместо гифки напр QProgressDialog, убедитесь что он работает, а потом и до гифки дело дойдет.
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #9 : Сентябрь 24, 2014, 11:40 »

QtConcurrent::run(myMethod) - не ?
вызывать руками процессевентс - это самому себе грабли раскидывать
Записан
OKTA
Гость
« Ответ #10 : Сентябрь 24, 2014, 12:08 »

Если планируется расширение в дальнейшем, то вынеси весь класс работы с БД в отдельный поток и не мучайся, а то так или processEvents везде распихивать или QtConcurrent::run постоянно дергать, если появятся новые тяжелые функции.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #11 : Сентябрь 24, 2014, 12:34 »

или QtConcurrent::run постоянно дергать, если появятся новые тяжелые функции.
Ну так он именно для этого и сделан. Улыбающийся
Он запускает пул потоков и нагружает их когда в этом есть необходимость.
Записан
OKTA
Гость
« Ответ #12 : Сентябрь 24, 2014, 12:38 »

Так-то да, но когда их много, могут быть проблемы с управлением  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #13 : Сентябрь 24, 2014, 12:40 »

Так-то да, но когда их много, могут быть проблемы с управлением  Улыбающийся
Проблемы с управлением могут быть только когда написано так, что есть проблемы с управлением, а так проблем с управлением быть не должно. Улыбающийся
Записан
OKTA
Гость
« Ответ #14 : Сентябрь 24, 2014, 12:49 »

Это в идеальном варианте  Улыбающийся
А так, например большая проблема QtConcurrentRun, что не остановишь его человеческим способом, когда потребуется. Вызывает геморрой, которого можно избежать, выделив все это барахло в честный отдельный поток  Улыбающийся
Во всяком случае лично меня всегда это коробило и я стараюсь пользоваться QtConucrrentRun только в случае небольших функций  Улыбающийся
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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