Название: Помогите добавить отображение прогресс диалога Отправлено: __Heaven__ от Апрель 26, 2018, 09:45 Привет, друзья!
Прошу помочь корректно решить задачу по добавлению прогресс диалога. Отображение самого прогреса операции не интересует. Хочу только антифриз окна. Сейчас имеется такая иерархия: MainWindow |=GLWidget |=MyModel |=MyObject - объект большого размера Модель предоставляет наружу указатель на объект Изменения объекта и модели испускают сигналы, которые связаны с GL опцией direct. MyModel::load(fileName) выглядит примерно так: Код: parser = selectParser(); Model::Load: Код: prepare(); Наивная передача Model::Load в поток через QtConcurent::run выливается в необновление GL и MainWindow. Да и результат он вызывает по значению, что для меня расточительно по использованию памяти Прошу поделиться мыслями, какое архитектурное решение здесь лучше применить. Пока вижу, что нужно как-то в главном потоке чистить объект, далее отображать прогресс и запускать парсер, который будет отправляться в поток, а по завершению делать перемещающее присваивание полученного объекта пустому. В таком способе не вижу, как оповестить основной поток о том, что операция чтения окончена Название: Re: Помогите добавить отображение прогресс диалога Отправлено: ViTech от Апрель 26, 2018, 15:14 Пока вижу, что нужно как-то в главном потоке чистить объект, далее отображать прогресс и запускать парсер, который будет отправляться в поток, а по завершению делать перемещающее присваивание полученного объекта пустому. В таком способе не вижу, как оповестить основной поток о том, что операция чтения окончена Сигнал о завершении чтения есть или как? Буду предполагать, что есть. Тогда, как вариант, метод Model::Load можно разделить на две части: первая выполняет подготовительные действия и отправляет в поток парсер, после этого завершается. Вторая часть оформлена слотом, который получает результат загрузки. Ещё может как-то QFutureWatcher поможет. Название: Re: Помогите добавить отображение прогресс диалога Отправлено: Igors от Апрель 27, 2018, 10:08 Хочу только антифриз окна. Обычно никакой активности юзера нельзя допускать пока идет загрузка. Поэтому просто модальный QProgressDialog, он сам вызовет processEvents. Ну конечно не забывать апдейтить диалог из загрузчика. "Вынос в поток" здесь не нужен.Тут правда одна бяка: в процессе загрузки рисование окон может ссылаться на данные что уже разрушены. Пресекается с помощью setUpdatesEnabled(false), хотя и с приключениями (недавно там ковырялся). Название: Re: Помогите добавить отображение прогресс диалога Отправлено: __Heaven__ от Май 01, 2018, 14:41 Сигнал о завершении чтения есть или как? Буду предполагать, что есть. Тогда, как вариант, метод Model::Load можно разделить на две части: первая выполняет подготовительные действия и отправляет в поток парсер, после этого завершается. Вторая часть оформлена слотом, который получает результат загрузки. Про вотчер я и забыл. Реализовал на нём.Ещё может как-то QFutureWatcher поможет. StartLoading запускает процесс, футуру, которого я передаю вотчеру, далее вотчер выполняет FinishLoading. Есть вопрос. У меня может случиться FinishLoading до завершения StartLoading или вообще не отработать завершение? Например, если потоку не особо много что нужно делать Столкнулся ещё с небольшой проблемой. Почему-то нельзя наполнять данными QOpenGLBuffer... Видимо, какие-то тонкости связанные с контекстом... Обычно никакой активности юзера нельзя допускать пока идет загрузка. Поэтому просто модальный QProgressDialog, он сам вызовет processEvents. Ну конечно не забывать апдейтить диалог из загрузчика. "Вынос в поток" здесь не нужен. Не, не хотелось такой связки. У меня предполагается несколько парсеров, возможно в будущем и внешние появятся. Придётся в каждом помимо парсинга заниматься и обновлением окна Название: Re: Помогите добавить отображение прогресс диалога Отправлено: ViTech от Май 02, 2018, 12:04 StartLoading запускает процесс, футуру, которого я передаю вотчеру, далее вотчер выполняет FinishLoading. Есть вопрос. У меня может случиться FinishLoading до завершения StartLoading или вообще не отработать завершение? Например, если потоку не особо много что нужно делать Параллельный поток с загрузкой вполне может завершиться до конца выполнения StartLoading, такую возможность отбрасывать нельзя. Другое дело, как, куда и когда вернётся результат загрузки. Сигнал QFutureWatcher::finished вполне можно соединить со слотом в вызывающем потоке по Qt::QueuedConnection, тогда StartLoading завершится и результат загрузки будет обработан в порядке очереди (сообщений). Вроде как-то так, надо на практике проверять :). Название: Re: Помогите добавить отображение прогресс диалога Отправлено: Igors от Май 02, 2018, 15:12 У меня предполагается несколько парсеров, возможно в будущем и внешние появятся. Придётся в каждом помимо парсинга заниматься и обновлением окна Так или иначе придется если хотите отображать ход загрузки(ок). Иногда удается проскочить привязавшись к сколько % считано из файла.Ну конечно конкретными окнами загрузчик не занимается, он обычно вызывает callback или испускает сигнал, а там уже обновят. Вообще не понял причем тут QtConcurrent если никакого параллелизма не требуется. Хотите непременно "в др потоке" (круто) - ну хорошо, тогда просто заведите рабочую QThread, создайте пресловутого worker'a и пульните его сигналом. Или QThreadPool, там еще меньше писать. В любом случае главная нитка свободна и проблема замерзания не стоит. Название: Re: Помогите добавить отображение прогресс диалога Отправлено: __Heaven__ от Май 03, 2018, 07:43 Вроде как-то так, надо на практике проверять :). Я рассуждал, что QFutureWatcher занимается опросом QFuture во время проворачивания EventLoop. Таким образом получается, что EventLoop заблокирован на момент выполнения StartLoading. Беспокойство вызывает момент присваивания результата run в QFuture и передача её в QFutureWatcher - не выполнился ли поток уже, иначе ж не стоит ожидать смены статуса QFuture.Igors, пробовал на processEvents выполнять обновление интерфейса - остались неприятные впечатления, связанные с уменьшением скорости выполнения вычислений. Не хочется возвращаться к этому варианту. С QThread мало работал, с QThreadPool вообще не работал. QThread, наверняка, потребует больше строк кода чем QtConcurrent::run. Пока не требуется отображать прогресс. Название: Re: Помогите добавить отображение прогресс диалога Отправлено: Igors от Май 04, 2018, 07:10 Igors, пробовал на processEvents выполнять обновление интерфейса - остались неприятные впечатления, связанные с уменьшением скорости выполнения вычислений. Не хочется возвращаться к этому варианту. Возможно Вы столкнулись с типовой проблемой - индикатор дергается слишком часто, в результате "работает на индикатор" (а не на расчеты). При выносе в поток это менее заметно, но решать все равно придется. Пока не требуется отображать прогресс. А как же тогда название темы ??? :)Неясно что Вы хотите обновлять. Модель грузится целиком, для нее создаются всякие внутренние структуры данных (хотя бы буфера рисования), поэтому что там обновлять в ходе загрузки - хз. Целиком загрузили, потом целиком отобразили - нормальная, стандартная практика. Название: Re: Помогите добавить отображение прогресс диалога Отправлено: Old от Май 04, 2018, 07:42 Я рассуждал, что QFutureWatcher занимается опросом QFuture во время проворачивания EventLoop. Нет. Скорее всего этот механизм сделан на условных переменных.Таким образом получается, что EventLoop заблокирован на момент выполнения StartLoading. Ничего не блокируется и весело крутится. :)Беспокойство вызывает момент присваивания результата run в QFuture и передача её в QFutureWatcher - не выполнился ли поток уже, иначе ж не стоит ожидать смены статуса QFuture. Нужно проверить, но скорее всего при помещении в вотчер уже завершенной задачи сигнал finished будет послан сразу. По крайней мере, это было бы логичным.Название: Re: Помогите добавить отображение прогресс диалога Отправлено: __Heaven__ от Май 17, 2018, 18:39 Ничего не блокируется и весело крутится. :) StartLoading ведь в том же потоке, где и processEvents (a.exe()). До веселья ещё одна } :)Нужно проверить, но скорее всего при помещении в вотчер уже завершенной задачи сигнал finished будет послан сразу. По крайней мере, это было бы логичным. Проверил. Под linux на Qt5.10. При return a.exec() выводится два сообщения, при return 0 - одно, но если вызвать a.processEvents(), то 2Сопутствующий вопрос появился: почему qDebug()<< "msg" в этом примере не работает? Подскажите, пожалуйста. Код
|