Название: Пауза Отправлено: Hero Sanya от Май 20, 2020, 13:26 Как ставить функцию, выполняющуюся в потоке, на паузу, при нажатии кнопки?
Я сделал кнопочку, которая собирает данные с полей для ввода и отправляет их в функцию обработки, из неё, в функцию расчёта, в другом потоке(функция очень большая и долго считающая). Мне нужно, чтобы можно было прерывать выполнение этой функции в любой момент (нажимать на паузу). Я даже не представляю, что должно происходить в коде, при нажатии на кнопку "пауза". Название: Re: Пауза Отправлено: Igors от Май 20, 2020, 14:34 Ну если "без затей" то просто sleep в цикле, напр
Код И повтыкать эту ф-цию в тело длинных расчетов. Ну а кнопочка устанавливает переменную pauseFlag. И, кстати, "прерывать" и "останавливать" не одно и то же Название: Re: Пауза Отправлено: Авварон от Май 20, 2020, 14:57 https://code.woboq.org/qt5/include/qt/QtCore/qfuture.h.html#_ZN7QFuture5pauseEv
https://code.woboq.org/qt5/qtbase/src/corelib/thread/qfutureinterface.cpp.html#_ZNK20QFutureInterfaceBase8isPausedEv https://code.woboq.org/qt5/qtbase/src/corelib/thread/qfutureinterface.cpp.html#_ZN20QFutureInterfaceBase13waitForResumeEv Название: Re: Пауза Отправлено: Hero Sanya от Май 20, 2020, 16:10 Ну если "без затей" то просто sleep в цикле, напр Код И по вставлять эту функцию в тело длинных расчетов. Кнопочка устанавливает переменную pauseFlag. И, кстати, "прерывать" и "останавливать" не одно и то же Так, то есть, обернуть всю функцию с расчётами в кокон из while(pauseFlag)? На само деле я не знаю что такое pauseFlag. Я к тому, что, нужны ли там библиотеки? И я так подразумеваю, что в итоге пауза будет ставится не сразу по нажатию кнопки, а пока она сигнал не поймает? Название: Re: Пауза Отправлено: Hero Sanya от Май 20, 2020, 16:12 https://code.woboq.org/qt5/include/qt/QtCore/qfuture.h.html#_ZN7QFuture5pauseEv О май гад. Что это за гиганский h. файлы?https://code.woboq.org/qt5/qtbase/src/corelib/thread/qfutureinterface.cpp.html#_ZNK20QFutureInterfaceBase8isPausedEv https://code.woboq.org/qt5/qtbase/src/corelib/thread/qfutureinterface.cpp.html#_ZN20QFutureInterfaceBase13waitForResumeEv Название: Re: Пауза Отправлено: Igors от Май 21, 2020, 10:47 Так, то есть, обернуть всю функцию с расчётами в кокон из while(pauseFlag)? Наоборот, вставить эту ф-цию в длинные расчеты, напр в тело циклаНа само деле я не знаю что такое pauseFlag. Обычная переменная (лучше член класса) которую Вам надо завестиЯ к тому, что, нужны ли там библиотеки? НетИ я так подразумеваю, что в итоге пауза будет ставится не сразу по нажатию кнопки, а пока она сигнал не поймает? Да, будет считать пока дело не дойдет до ф-цииhttps://code.woboq.org/qt5/include/qt/QtCore/qfuture.h.html#_ZN7QFuture5pauseEv Танки вперед :) Я всегда считал футуру бездарной, ну может я не прав. Можно пример (пседокод, словами, как угодно) как ее задействовать в данном случае? Спасибоhttps://code.woboq.org/qt5/qtbase/src/corelib/thread/qfutureinterface.cpp.html#_ZNK20QFutureInterfaceBase8isPausedEv https://code.woboq.org/qt5/qtbase/src/corelib/thread/qfutureinterface.cpp.html#_ZN20QFutureInterfaceBase13waitForResumeEv Название: Re: Пауза Отправлено: Пантер от Май 21, 2020, 11:16 Я бы не стал использовать циклы со слипом, ибо это костыльное решение. На счет QFuture ничего сказать не могу, но я не уверен, что там так все просто, твой код должен поддерживать приостановку (если не прав, поправьте, самому лень читать доки).
Я поступил бы по-другому - реализовал расчеты так, чтобы можно было либо безболезненно остановить их, сохранив промежуточные результаты. Если это никак не получается, то хотя бы сделать все по-нормальному, используя QMutex, QSemaphore, QWaitCondition. Название: Re: Пауза Отправлено: Igors от Май 21, 2020, 12:01 ...ибо это костыльное решение. Да. Зато "дешево, удобно, практично".Я поступил бы по-другому - реализовал расчеты так, чтобы можно было либо безболезненно остановить их, сохранив промежуточные результаты. Если это никак не получается, .. Такая возможность выпадает редко. Обычно расчет наструячит массу своих данных, объектов и.т.п. и сохранить/восстановить этот "контекст" оказывается неподъемным...то хотя бы сделать все по-нормальному, используя QMutex, QSemaphore, QWaitCondition. Как только Вы попробуете привести пример "по-нормальному" - все окажется очень непросто :)Название: Re: Пауза Отправлено: Авварон от Май 21, 2020, 18:42 Я поступил бы по-другому - реализовал расчеты так, чтобы можно было либо безболезненно остановить их, сохранив промежуточные результаты. Если это никак не получается, то хотя бы сделать все по-нормальному, используя QMutex, QSemaphore, QWaitCondition. И это ровно то что делает QFutureInterface=) На самом деле надо попедалировать рассылку Qt на тему того чтобы переименовать его в QPromise и таки задокументировать (это уже всплывало ~месяц назад но как всегда заглохло) Название: Re: Пауза Отправлено: Hero Sanya от Май 21, 2020, 22:42 Так. В общем, я сделал три кнопки:Пауза, продолжить и старт. Старт запускает программу и она сидит в цикле(пока, не тру), если паузы так и не произошло, то просто выйдет из него поставив тру. По пути она будет считывать файл в котором будет лежать ключ(ну просто код), собственно этот код изменяется нажатием пауза. То есть пауза, просто берёт файл, переписывает его содержимое в единичку(можно сказать что это ключ для паузы). собственно, когда глобальная функция прочтёт из файла единицу, она войдёт в замкнутый цикл.На всякий случай я там оставил таймер. там тоже происходит чтение файла и если была нажата кнопка продолжить, файл пере пишется ну, на любую другую цифру(например 2). То есть файлом, можно игнорировать такую вещь, как потоки и передавать послания в любые другие потоки или основной. Можете назвать это костылём, но это работает идеально, так ещё и оставляет возможность для модификаций, например для сериализации кода(что пригодится для сохранения и загрузки).
В итоге: Пауза и продолжить, просто переписывают по нажатию кнопки текст в файле, а циклы являются скажем так, контрольными точками или чекпоинтами. Название: Re: Пауза Отправлено: Hero Sanya от Май 21, 2020, 23:01 Если кому нужно, я приложу своё решение проблемы с паузой. Однако, тут я всё ещё не знаю, как реализовать неактивные кнопки(НО я думаю, это тема другой..эмм. темы). Так же, я считаю. что тут единственная дыра, это когда пользователь нажмёт на кнопку во время чтения из файла. С другой стороны, для выхода из паузы, можно придумать один единственный код: какие нибудь 8888, да он пропустит одну итерацию в цикле, но в итоге всё ровно продолжит программу.
.h Код: #ifndef THREE_H Код: #include "mainwindow.h" Код: MainWindow::MainWindow(QWidget *parent) Код: bool stoper=false; Название: Re: Пауза Отправлено: Пантер от Май 21, 2020, 23:02 >То есть файлом, можно игнорировать такую вещь, как потоки и передавать послания в любые другие потоки или основной
Угу. А про кеширование файловой системы ты не слышал? Обрабатываешь ситуацию, если файл пустой? А если двое сразу запишут в него что-нибудь? Название: Re: Пауза Отправлено: Hero Sanya от Май 21, 2020, 23:45 >То есть файлом, можно игнорировать такую вещь, как потоки и передавать послания в любые другие потоки или основной Это просто пример паузы. Переписывать файл могут только пауза и продолжить(просто в этом примере они активны одновременно, что ошибка). Угу. А про кеширование файловой системы ты не слышал? Обрабатываешь ситуацию, если файл пустой? А если двое сразу запишут в него что-нибудь? На счёт игнорирования, я имел ввиду, что можно организовать общение потоков через файловую систему. Да, тут нету обработок на случай если файл пустой, просто я в маинвиндовс, сразу создаю файл заполненным. Другое дело. если кто то целенаправленно захочет удалить или переписать файл(ну а это ровно тоже самое, если переписать любой файл программы). Название: Re: Пауза Отправлено: Igors от Май 22, 2020, 10:21 То есть файлом, можно игнорировать такую вещь, как потоки и передавать послания в любые другие потоки или основной. Можете назвать это костылём, но это работает идеально, так ещё и оставляет возможность для модификаций, например для сериализации кода(что пригодится для сохранения и загрузки). Обычно подобные городушки лепятся для процессов (впрочем и там это плохо), но для потоков, где память общая, зачем же читать файл в цикле?Цитировать — Но зачем же брить яйца наголо, поручик? — Дикари-с. И это ровно то что делает QFutureInterface=) Не слышал о таком, но рискну утверждать что для данной задачи (т.е. (при)остановить один но длинный расчет) он ничем не поможет. Т.к. задача по своей природе "интрузивна", т.е. ф-ция останова должна быть внедрена в код расчетов, сделать это чисто "извне" невозможно. Вообще затрудняюсь вспомнить случай когда мне нужно было чего-то там "подсматривать" при параллельном выполнении. Индикатор - да, а вот тот же (при)останов - крайне редко. Обычно нужно выжать скорость, поэтому все эти футуры, промисы и.т.п. мне без надобности. Название: Re: Пауза Отправлено: Пантер от Май 22, 2020, 10:40 Соглашусь с Igors, для возможности останова должен быть модифицирован код. А любое добавление проверок или индикации в код расчета замедлит его в разы. Если возможно, можно разбить расчет на несколько этапов и делать проверки между этими этапами. Соответственно, в данном случае можно будет и сохранить текущее состояние расчетов.
Название: Re: Пауза Отправлено: Авварон от Май 22, 2020, 10:45 А любое добавление проверок или индикации в код расчета замедлит его в разы. Если возможно, можно разбить расчет на несколько этапов и делать проверки между этими этапами. Соответственно, в данном случае можно будет и сохранить текущее состояние расчетов. Если что, проверка на паузу - это атомарная переменная с relaxed memory order. Если relaxed проверка тормозит расчёты то может стоит подумать о том что расчёты вообще не должны быть в потоке?=) Название: Re: Пауза Отправлено: Igors от Май 22, 2020, 12:55 А любое добавление проверок или индикации в код расчета замедлит его в разы. Ну как.. это типовая проблема/ошибка - переборщить с индикатором. Но если делать аккуратно, то все норм, напрКод
Если что, проверка на паузу - это атомарная переменная с relaxed memory order. Если relaxed проверка тормозит расчёты то может стоит подумать о том что расчёты вообще не должны быть в потоке?=) Собсно "проверка" - да, но нужно как-то поток остановить, и футуры здесь не помогут. И вообще, Вы прямо терроризируете начинающих. "relaxed memory order" - бог весть что можно подумать, а это всего лишь самое обычное чтение переменной :) Ну если уж и оно тормозит...И, кстати, как бум останавливать "по-нормальному" ? (sleep не есть хорошо). Давайте Вы на QWaitCondition, а я на своем любимом QSemaphore Название: Re: Пауза Отправлено: Авварон от Май 22, 2020, 13:13 И, кстати, как бум останавливать "по-нормальному" ? (sleep не есть хорошо). Давайте Вы на QWaitCondition, а я на своем любимом QSemaphore Код: void foo(QFutureInterface<int> promise) А вы продолжайте писать велосипеды с семафором=) Да, чтобы иметь возможность запускать через промис, надо потырить вот этот файлик из QtCreator, всячески рекомендую (его переписали на вариадики, кстати) https://code.woboq.org/qt5/qt-creator/src/libs/utils/runextensions.h.html Запускать так: Код: #include "runextensions.h" Название: Re: Пауза Отправлено: Igors от Май 22, 2020, 18:45 Код: void foo(QFutureInterface<int> promise) А вы продолжайте писать велосипеды с семафором=) Да, чтобы иметь возможность запускать через промис, надо потырить вот этот файлик из QtCreator, всячески рекомендую (его переписали на вариадики, кстати) https://code.woboq.org/qt5/qt-creator/src/libs/utils/runextensions.h.html Запускать так: Код: #include "runextensions.h" Название: Re: Пауза Отправлено: Пантер от Май 22, 2020, 18:56 Igors, перечитай код еще раз, он очень простой и все в нем нормально.
Название: Re: Пауза Отправлено: Igors от Май 23, 2020, 07:33 Igors, перечитай код еще раз, он очень простой и все в нем нормально. Перечитал, рез-т тот же :)И вообще, в чем "хотелка"? Иметь удобные вызовы индикатор/пауза/отмена ? Все. что ли? Если так то эти мелкие подробности легче пристроить самому (если еще они понадобятся) чем забивать голову монструозными классами с мизерным ф-ционалом. Проблемы "разпоточивания" совсем в другом. В любой системе это ведь только так предполагается что есть/имеются N задач которые могут выполняться одновременно, на самом деле выделить/создать их часто очень непросто. Название: Re: Пауза Отправлено: Пантер от Май 23, 2020, 09:18 Igors, перечитай код еще раз, он очень простой и все в нем нормально. Перечитал, рез-т тот же :)И вообще, в чем "хотелка"? Иметь удобные вызовы индикатор/пауза/отмена ? Все. что ли? Если так то эти мелкие подробности легче пристроить самому (если еще они понадобятся) чем забивать голову монструозными классами с мизерным ф-ционалом. Проблемы "разпоточивания" совсем в другом. В любой системе это ведь только так предполагается что есть/имеются N задач которые могут выполняться одновременно, на самом деле выделить/создать их часто очень непросто. Эта штука для того, чтобы каждый не пилил свой велосипед с незащищенным доступом к переменным, а юзал защищенные и быстрые вызовы. Название: Re: Пауза Отправлено: Igors от Май 23, 2020, 10:17 Странно, этот код будет понятен даже джуну... Думаю что нет. Ну если конечно джун не делает вид что, мол, ему все понятно :). Ну в самом делеКод: void foo(QFutureInterface<int> promise) И кто/как ставит на паузу? Наверно надо эту футуру подать в расчет, а там уж вызвать ее метод (а как иначе?). Опять только догадки, лучшего нет. А Вы говорите "все ясно" Эта штука для того, чтобы каждый не пилил свой велосипед с незащищенным доступом к переменным, а юзал защищенные и быстрые вызовы. Какие? Пауза что нужна в году раз и которую сделать 5 минут? И ради этого тащить немалый кусок темплейтовской срани? Та ну нафиг. И, кстати, вещь совсем не новая, но документировать не спешат, видимо сами "не удовлетворены"Название: Re: Пауза Отправлено: Авварон от Май 23, 2020, 13:21 И кто/как ставит на паузу? Наверно надо эту футуру подать в расчет, а там уж вызвать ее метод (а как иначе?). Опять только догадки, лучшего нет. А Вы говорите "все ясно" В расчёт вы подаете promise. На паузу ставит футура: Код: #include "runextensions.h" Название: Re: Пауза Отправлено: Пантер от Май 23, 2020, 13:23 Хм, не думал, что все так туго...
Код - это и есть весь расчет. Ты же не думал, что тебе тут напишут код расчета зависимости стоимости молока в средней полосе России от скорости сборки апельсинов во Вьетнаме. В данном примере показана логика использования данной схемы, не указан только момент останова, но, думаю, это будет всего-лишь проверка Код
Название: Re: Пауза Отправлено: Igors от Май 25, 2020, 10:41 А! Т.е. qHash имитирует одну итерацию расчетв. Действительно, все просто, это я туплю :)
Ну хорошо, а что, QtConcurrent не обеспечивает этого ф-ционала (отмена/пауза)? (видел там подобные методы). Откуда возникла необходимость (или энтузиазм) юзать недокументированные фичи? Название: Re: Пауза Отправлено: Авварон от Май 25, 2020, 17:53 А! Т.е. qHash имитирует одну итерацию расчетв. Действительно, все просто, это я туплю :) Ну хорошо, а что, QtConcurrent не обеспечивает этого ф-ционала (отмена/пауза)? (видел там подобные методы). Откуда возникла необходимость (или энтузиазм) юзать недокументированные фичи? Функции типа map(), reduce() умеют, а вот QtConcuent::run() не умеет, так как не передает QFutureInterface в юзерскую функцию. Вот этот хедер из QtCreator'а делает ровно то же самое, что делает QtConcuent::run(), только первым параметром передает QFutureInterface. Это в нем юзается повсеместно - например, когда парсится проект и бежит прогрессбар справа в углу - это вот оно (да, QFutureInterface еще умеет и прогресс репортить). Название: Re: Пауза Отправлено: alexu007 от Май 29, 2020, 23:07 Пауза:
Код
|