Название: Длительные операции + QtConcurrent Отправлено: Nidxogg от Сентябрь 23, 2014, 18:17 Добрый день.
Есть gui-программа, работающая с БД. Все запросы и т.д вынесены в отдельный класс. Все работает в одном потоке. Есть такой псевдокод, который должен выполнится строго в заданной последовательности. Код: void MyClass::myMethod() Собственно func2() выполняется довольно долго, поэтому решил на время фриза интерфейса добавить гифку-прогрессбар(+QMovie) . Гифка, естественно, не анимируется в процессе выполнения func2(). processEvent() не помог. Тогда решил выполнить func2() в отдельном потоке с использованием QtConcurrent::run(...), гифка ожила, но теперь func3() начинает выполняться до окончания func2(); Пробовал использовать waitForFinished, но опять столкнулся с фризом интерфейса. Может у кого-нибудь есть идеи как выйти из ситуации? Название: Re: Длительные операции + QtConcurrent Отправлено: Bepec от Сентябрь 23, 2014, 18:22 Видимо вы как то не так делали processEvents :) Всё должно работать без фризов.
Название: Re: Длительные операции + QtConcurrent Отправлено: Old от Сентябрь 23, 2014, 18:23 Запускайте func3 в слоте, который будет вызываться при завершении потока, выполняющего func2.
Название: Re: Длительные операции + QtConcurrent Отправлено: Nidxogg от Сентябрь 23, 2014, 18:44 Цитировать Запускайте func3 в слоте, который будет вызываться при завершении потока, выполняющего func2. Вы имеет ввиду соединить сигнал finished() от QFutureWatcher со слотом, и вызывать func3() там?прим.: мне приходит несколько пакетов по сети практически одновременно, которые необходимо обработать. В слоте я вызываю myMethod и рассчитываю, что обработка следующего пакета не начнется, пока не завершится обработка текущего (собственно так и работает, т.к все в одном потоке(если без QtConcurent)). Не получился ли, что я вызову myMethod раньше, чем завершится выполнение func3()? Цитировать Видимо вы как то не так делали processEvents Всё должно работать без фризов. У меня прозрачный виджет ставится, аналог вашего sbglass (qlightboxwidget в гугле), на который кидается QLabel и гифка.processEvents вызываю qApp->processEvents() во время обработки запроса из БД (Порядка 150 раз в течение ~5 секунд); Название: Re: Длительные операции + QtConcurrent Отправлено: Igors от Сентябрь 23, 2014, 18:52 Гифка, естественно, не анимируется в процессе выполнения func2(). processEvent() не помог. Не вижу здесь ничего естественного, надо разбираться. Вообще запуск потока только с целью обеспечить индикатор не есть хорошо/грамотно.Название: Re: Длительные операции + QtConcurrent Отправлено: Nidxogg от Сентябрь 23, 2014, 19:25 Цитировать Не вижу здесь ничего естественного, надо разбираться Главный поток загружен операциями в func2, интерфейс зафрижен.Что не так? Название: Re: Длительные операции + QtConcurrent Отправлено: Bepec от Сентябрь 23, 2014, 20:58 Не так, что достаточно 25 раз в секунду вызывать processEvents чтобы пользователь вообще ничего не заподозрил.
Значит вы его вызываете или не там, или не так :) Т.е. вот такое высказывание верно: Главный поток загружен операциями в func2, где вызывается processEvents, интерфейс работает нормально. Название: Re: Длительные операции + QtConcurrent Отправлено: VPS от Сентябрь 23, 2014, 22:58 Что Вам мешает все три метода обработки данных запускать последовательно в отдельном потоке, а принимаемые пакеты из главного (GUI или другого) потока передавать туда на обработку? В данном случае, для передачи пакетов, можно попробовать использовать сигналы или библиотеку, в которой есть потокобезопасная очередь. Т.е. получится что-то типа шаблона Producer-Consumer.
Название: Re: Длительные операции + QtConcurrent Отправлено: Igors от Сентябрь 24, 2014, 06:19 Главный поток загружен операциями в func2, интерфейс зафрижен. А что "так"? :) То что есть интенсивный расчет - еще не основание выносить его в отдельный поток. Вот напр если 2 расчета параллельно - тогда да. А так гораздо проще вызывать processEvents в теле расчета. 25 раз в сек - ну это для видео, а для UI достаточно и 5 раз. Попробуйте вместо гифки напр QProgressDialog, убедитесь что он работает, а потом и до гифки дело дойдет.Что не так? Название: Re: Длительные операции + QtConcurrent Отправлено: qate от Сентябрь 24, 2014, 11:40 QtConcurrent::run(myMethod) - не ?
вызывать руками процессевентс - это самому себе грабли раскидывать Название: Re: Длительные операции + QtConcurrent Отправлено: OKTA от Сентябрь 24, 2014, 12:08 Если планируется расширение в дальнейшем, то вынеси весь класс работы с БД в отдельный поток и не мучайся, а то так или processEvents везде распихивать или QtConcurrent::run постоянно дергать, если появятся новые тяжелые функции.
Название: Re: Длительные операции + QtConcurrent Отправлено: Old от Сентябрь 24, 2014, 12:34 или QtConcurrent::run постоянно дергать, если появятся новые тяжелые функции. Ну так он именно для этого и сделан. :)Он запускает пул потоков и нагружает их когда в этом есть необходимость. Название: Re: Длительные операции + QtConcurrent Отправлено: OKTA от Сентябрь 24, 2014, 12:38 Так-то да, но когда их много, могут быть проблемы с управлением :)
Название: Re: Длительные операции + QtConcurrent Отправлено: Old от Сентябрь 24, 2014, 12:40 Так-то да, но когда их много, могут быть проблемы с управлением :) Проблемы с управлением могут быть только когда написано так, что есть проблемы с управлением, а так проблем с управлением быть не должно. :)Название: Re: Длительные операции + QtConcurrent Отправлено: OKTA от Сентябрь 24, 2014, 12:49 Это в идеальном варианте :)
А так, например большая проблема QtConcurrentRun, что не остановишь его человеческим способом, когда потребуется. Вызывает геморрой, которого можно избежать, выделив все это барахло в честный отдельный поток :) Во всяком случае лично меня всегда это коробило и я стараюсь пользоваться QtConucrrentRun только в случае небольших функций :) Название: Re: Длительные операции + QtConcurrent Отправлено: Old от Сентябрь 24, 2014, 12:56 А так, например большая проблема QtConcurrentRun, что не остановишь его человеческим способом, когда потребуется. Все останавливается точно так же как и с отдельным потоком, через флажочек. :)Название: Re: Длительные операции + QtConcurrent Отправлено: OKTA от Сентябрь 24, 2014, 13:14 Флажочек да, без него никуда. Но лично меня большое количество QtConcurrent настораживает и пугает. Превращается в какой-то зоопарк, за которым тяжко следить и тем более разбираться в коде. :) Про случай, когда надо мильён одинаковых функций вызвать в отдельных потоках я не говорю.
В общем, субъективно это все ;D Название: Re: Длительные операции + QtConcurrent Отправлено: Nidxogg от Сентябрь 24, 2014, 18:07 С processEvents() решил проблему
Оказалось, случайно, не в тот цикл его вставил (с малым число итераций) Цитировать Если планируется расширение в дальнейшем, то вынеси весь класс работы с БД в отдельный поток и не мучайся, а то так или processEvents везде распихивать или QtConcurrent::run постоянно дергать, если появятся новые тяжелые функции. Так изначально и планировалось, но не пошло по некоторым причинам.Цитировать QtConcurrent::run(myMethod) - не ? Мне его иногда приходится вызывать чаще, чем он успевает отработать. Разве что создать какую-то очередь на обработку или мьютексами обложить Цитировать вызывать руками процессевентс - это самому себе грабли раскидывать ?Название: Re: Длительные операции + QtConcurrent Отправлено: qate от Сентябрь 25, 2014, 09:20 Цитировать вызывать руками процессевентс - это самому себе грабли раскидывать ?если обработчики сигналов не реентерабельны - будут проблемы Название: Re: Длительные операции + QtConcurrent Отправлено: Igors от Сентябрь 25, 2014, 10:43 если обработчики сигналов не реентерабельны - будут проблемы Возможно имелось ввиду что processEvents разрешает др события/сигналы которые могут изменить контекст расчета, а то и вовсе удалить используемые в расчете данные. Да, от этого надо страховаться (часто модальностью) - но это так же и в др случаях...то вынеси весь класс работы с БД в отдельный поток и не мучайся, а то так или processEvents везде распихивать И что изменит этот вынос? События-то все равно разрешены, теперь потому что главная нитка свободна. И все равно надо знать "а что же там с расчетом", поэтому что-то пихать в него все равно надо. Название: Re: Длительные операции + QtConcurrent Отправлено: OKTA от Сентябрь 25, 2014, 10:54 Да, пихать надо, но с возрастанием количества разнообразных расчетов и обращений к бд, будет все сложнее держать это в одном классе и тем более следить за этим барахлом, запускаемым через QtConcurrent.
|