Название: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Сентябрь 14, 2012, 14:26 Встала задача выполнения долгой операции в треде. Казалось бы - берем QtConcurrent и пользуемся. Но не тут-то было - в документации к QtConcurrent::run написано:
Цитировать Note that the QFuture returned by QtConcurrent::run() does not support canceling, pausing, or progress reporting. The QFuture returned can only be used to query for the running/finished status and the return value of the function. Погуглив, я ничего не нашел и полез в сорцы креатора. Оказывается, там есть чудный файлик runextensions.h (который можно, при желании, легко написать самому), который добавляет возможность уведомлять о прогрессе выполнения функции.Вот пример использования (проект и runextensions.h можно скачать в аттаче): Функция запускает задачу в потоке, а та пишет прогресс в диалог. Также можно отменить задачу кнопкой на диалоге. Код: #include <QApplication> Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Май 19, 2015, 21:26 Спасибо за находку! В документации об этом ни гу-гу.
Цитировать Погуглив, я ничего не нашел и полез в сорцы креатора. Оказывается, там есть чудный файлик runextensions.h (который можно, при желании, легко написать самому), который добавляет возможность уведомлять о прогрессе выполнения функции. А почему нельзя, например, передать объект QFuture напрямую в doWork()? Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Май 22, 2015, 13:35 Потому что футура предназначена для чтения, ее нельзя (нет API) менять. Для этого сделан FurureInterface (aka std::promise)
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Май 22, 2015, 18:04 Понятно, спасибо. Правда я вызываю метод класса и у меня выдаёт ошибку при компиляции:
Цитировать c:\qt\4.8.6\src\corelib\concurrent\qtconcurrentrun.h:115: error: C2064: term does not evaluate to a function taking 1 arguments Пытаюсь по Вашей аналогии вызвать: Код: QFuture<void> backgroundJob = QtConcurrent::run(report, &XMLReport::Export); Определение этого метода в классе: Код: void XMLReport::Export(QFutureInterface<void> &future) Как такой метод можно вызвать? А если он ещё и виртуальный (virtual) - вызовется ли правильный метод в наследуемом классе? Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Май 24, 2015, 00:18 Попробовал обёртки по типу как написано в Qt - всё равно эта ошибка вылетает при компиляции, видимо это фишка только 5-й Qt, а в qt 4.8.6 не работает. Или нет?
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Май 30, 2015, 09:44 Потому что у вас мембер ф-ия, надо this передать.
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Май 30, 2015, 12:44 Я передавал this, сделал обёртку над мембер функцией, всё равно ошибку выбивает, потому, что мне QFutureInterface туда передать нужно. Пришлось сигналы привязать напрямую в контейнере классов, а хотелось бы конечно спрятать внутри класса XMLReport и диалога с ProgressBar, передав им только QFutureInterface&.
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 02, 2015, 19:08 Вы runextensions.h вообще скачали?)
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 02, 2015, 23:34 Конечно! :) Первым делом. И подключил.
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: __Heaven__ от Июнь 03, 2015, 11:11 Да, забавненько, что про QFutureInterface нет статейки в доках. Я же для отображения прогресса использовал общие переменные. Из прогрессдиалога считывал каждые 100мс.
А в qthread как-то можно следить за прогрессом иначе? Не понятен смысл строчки Цитировать Note that the QFuture returned by QtConcurrent::run() does not support canceling, pausing, or progress reporting. Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 03, 2015, 16:35 Да, забавненько, что про QFutureInterface нет статейки в доках. Я же для отображения прогресса использовал общие переменные. Из прогрессдиалога считывал каждые 100мс. А в qthread как-то можно следить за прогрессом иначе? Не понятен смысл строчки Цитировать Note that the QFuture returned by QtConcurrent::run() does not support canceling, pausing, or progress reporting. Как раз понятен - т.к. интерфейс в ф-ии не передается, то она и не поддерживает. AlekseyK Это странно, т.к. у вас он пытается юзать оверлоады из qtcore, судя по выхлопу компилятора. Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 03, 2015, 16:41 AlekseyK Это странно, т.к. у вас он пытается юзать оверлоады из qtcore, судя по выхлопу компилятора. Видимо так, не знаю как его нужно было заставить использовать runextensions, потратил много времени и так и сяк - не собралось, поэтому пока сигналы привязал напрямую. А хотелось бы конечно их спрятать внутри классов и передавать только QFutureInterface. Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 03, 2015, 16:45 Пример у вас работает? Пробовали добавить туда мембер ф-ию?
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 03, 2015, 16:59 Пример у вас работает? Пробовали добавить туда мембер ф-ию? Пример работает, если переделать на мембер функцию - не собирается: Код
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 03, 2015, 17:03 Ну сигнатуру ф-ии всё-таки смотреть надо:)
Код: QtConcurrent::run(&Work::doWork, &work); Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 03, 2015, 17:07 ДААААА???? :)))))))))))))) Сейчас попробуем ещё тогда. :) Спасибо! Вот на это-то времени и не хватило разобраться.
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 03, 2015, 17:15 Ну как бэ
Код: template <typename Class, typename T> Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 03, 2015, 17:24 Ну да, но на примерах оно лучше :)
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 03, 2015, 18:27 Собралось, спасибо! Попробуем переключить сигналы.
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 03, 2015, 18:50 Ура! Всё заработало, можно отмечать тему как решённую!
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 12, 2015, 19:34 Правда ещё одна проблема всплыла, не всё так красиво получилось как хотелось: сигналы из процесса не все доходят до диалога, останавливаются где-то на 60-95% почему-то: значение и текст. Пришлось опять привязать сигналы напрямую: Процесс -> ProgressDialog. Что за ерунда, почему так происходит? Если привязываем процесс -> вызов QFutureInterface::setProgressValueAndText(progressValue, message) -> ProgressDialog, то сигналы теряются в конце.
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 12, 2015, 20:38 Хз, не замечал. Установка значения происходит? как обрабатываете finished? репортите ли завершение?
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 12, 2015, 21:45 Хз, не замечал. Установка значения происходит? Конечно, процесс заканчивается так:Код
как обрабатываете finished? Код
репортите ли завершение? Вызывается точно, т.к. кнопка ВСЕГДА меняет текст на "Done!", значит future или futureWatcher вызывает finished().Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 12, 2015, 22:56 Футуру лучше ставить после коннектов. Можете схематичный код таски привести?
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 12, 2015, 23:09 Футуру лучше ставить после коннектов. Можете схематичный код таски привести? Конечно. XML экспорт, где после каждой секции выводится:Код
Код
future() возвращает QFutureInterface, который передаётся при запуске процесса. Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Igors от Июнь 13, 2015, 06:27 Боже, как это все запутано, навязывается какая-то футура, с которой надо мучительно разбираться... Не лучше ли по-простому: завести атомарный счетчик и делать ему ++ в каждом расчете. А главная нитка следит за ним по таймеру и обновляет индикатор. Так по крайней мере нет расходов на сигналы (а то часто работает на индикатор а не на расчет).
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 13, 2015, 10:07 Не лучше ли по-простому: на ассемблере? Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Old от Июнь 13, 2015, 10:54 Боже, как это все запутано, навязывается какая-то футура, с которой надо мучительно разбираться... Не лучше ли по-простому: завести атомарный счетчик и делать ему ++ в каждом расчете. А главная нитка следит за ним по таймеру и обновляет индикатор. Так по крайней мере нет расходов на сигналы (а то часто работает на индикатор а не на расчет). К сожалению, задач может быть больше одной, соответственно и индикаторов понадобиться больше одного, значит и атомарный счетчик понадобиться не один.В общем, получится еще запутанней, чем здесь. :) Хотя я ничего запутанного в future не наблюдаю. Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Igors от Июнь 13, 2015, 11:47 Кстати о птичках: а что произойдет если задача выбросит исключение?
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 13, 2015, 15:18 Кстати о птичках: а что произойдет если задача выбросит исключение? Вы так кичитесь тем, что не читаете букварь, что регулярно ставите себя в дурацкое положение. Не позорьтесь, почитайте. Гугл std::future, std::promise. Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: AlekseyK от Июнь 13, 2015, 19:57 Это всё интересно и познавательно, но всё же почему не все сигналы от future доходят?
Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Old от Июнь 13, 2015, 20:00 Это всё интересно и познавательно, но всё же почему не все сигналы от future доходят? Вы бы выложили компилябельный пример, как вы это делаете. Был бы проще.Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Igors от Июнь 14, 2015, 10:10 Кстати о птичках: а что произойдет если задача выбросит исключение? Вы так кичитесь тем, что не читаете букварь, что регулярно ставите себя в дурацкое положение. Не позорьтесь, почитайте. Гугл std::future, std::promise. А зачем мне их читать если я использую OpenMP - что на мой взгляд гораздо мощнее и солиднее. Заметьте, я не говорю Вам "не позорьтесь, читайте OpenMP" :)std - стандартные решения популярных задач. Ну вот не было футуры, надо было городить флажок, как-то организовать ожидание, вот сделали что-то штатное, ну молодцы, спасибо. Но откуда глупейшее предубеждение что этим штатным обязательно, непременно нужно пользоваться, иначе - несмываемый позор? :) Даже "чисто объективно" никто не обещал что оно окажется здесь лучшим. Напр та же посылка сигналов может заметно тормозить если единица задачи мала. Вы определенно "заучились" - поверьте, не тот программист лучше кто "больше знает" :) Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Old от Июнь 14, 2015, 10:37 А зачем мне их читать если я использую OpenMP А зачем тогда вопросы задаете, если оно вам не надо? :)что на мой взгляд гораздо мощнее и солиднее. Детский сад. :)Название: Re: QtConcurrent::run с прогрессом выполнения Отправлено: Авварон от Июнь 14, 2015, 11:20 ??? Да я здесь даже слова "букварь" не говорил :) И как это связано с вопросом про исключение? А зачем мне их читать если я использую OpenMP - что на мой взгляд гораздо мощнее и солиднее. Заметьте, я не говорю Вам "не позорьтесь, читайте OpenMP" :) Вы определенно "заучились" - поверьте, не тот программист лучше кто "больше знает" :) Да-да, не тот, кто больше знает, а кто городит свои велосипеды потому что "букварь для лохов". |