Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: Igors от Январь 30, 2016, 15:13



Название: ThreadControl suspend/resume/abort
Отправлено: Igors от Январь 30, 2016, 15:13
Добрый день

Навеяно этой (http://www.prog.org.ru/index.php?topic=29697.msg218099#msg218099) темой. Полагаем что мы не используем QThread::exec, а сами делаем все свои дела в QThread::run. И вот казалось бы, "простейшая задача" - надо нитку остановить а потом снять с останова. Но я не вижу никакого простого способа это сделать. Если чего-то не нашел - please "ткните носиком" :)

Не, ну конечно можно так
Код
C++ (Qt)
void MyThread::run( void )
{
while (!mAbortFlag) {
 while (mPauseFlag)
   msleep(SOME_DELAY);
 
  // do job
}
}
Несмотря на привлекающую простоту использование sleep в рабочем коде (не для отладки/примера) надо признать малодушным решением. Кроме того здесь протаскивается предположение что управляющая нитка (которая меняет mAbortFlag и mPauseFlag) всего одна, напр главная. Как только их будет 2 и больше - так просто уже не выйдет.

В аттаче попытка сделать "по-взрослому", с ожиданием на семафоре. Ф-ционал собран в отдельный класс который можно цеплять членом или множ наследованием к QThread но не только.

Примечание для тех у кого опыта мало
Цитировать
Я вот нажал Enter, напечатала "Suspended..", потом еще все нитки сработали по разу...
Это нормально, "мгновенно" нитку не остановить, дело должно дойти до проверки

Это все, благодарю за внимание


Название: Re: ThreadControl suspend/resume/abort
Отправлено: Old от Январь 30, 2016, 16:08
Ну теперь понятно, каким боком вы туда семофор сватали. :) Но у автора той темы один флаг с условной переменной на все потоки (для пула так удобней), а у вас по семафору на поток.

В аттаче попытка сделать "по-взрослому", с ожиданием на семафоре.
А в чем вы видите взрослость решения? Мне это напомнило: "Мы научим вас делать сложно простые вещи". :)

Я вообще не понимаю, где может понадобиться установка потока на паузу? Рабочие потоки могут спать в ожидании работы, их нужно остановить при завершении работы программы, но поставить их на паузу? Для чего?


Название: Re: ThreadControl suspend/resume/abort
Отправлено: AkonResumed от Октябрь 18, 2020, 20:37
Ну, например, в Win API есть ref-counted SuspendThread/ResumeThread. Элементарный юзкейс - например, вычисляете 10-ю потоками некое сложное значение, юзер ждет, но решает поставить операцию на паузу и выполнить другое жирное вычисление.

Т.е. такие функции (заметьте, они со счетчиком, и могут быть заюзаны из разных потоков) избавляют от замусоливания рабочего кода всякими проверками флагов паузы.


Название: Re: ThreadControl suspend/resume/abort
Отправлено: Igors от Октябрь 19, 2020, 12:29
Ну, например, в Win API есть ref-counted SuspendThread/ResumeThread. Элементарный юзкейс - например, вычисляете 10-ю потоками некое сложное значение, юзер ждет, но решает поставить операцию на паузу и выполнить другое жирное вычисление.

Т.е. такие функции (заметьте, они со счетчиком, и могут быть заюзаны из разных потоков) избавляют от замусоливания рабочего кода всякими проверками флагов паузы.
Не прошло и пятилетки как это вызвало некоторый интерес :) Ну во-первых насколько кросс-платформенно такое решение? Или это подробности личной жизни Win API ? Ладно, бегло глянем

Цитировать
Эта функция, прежде всего, разработана для использования отладчиками. Она не предназначена использоваться для синхронизации потока. Вызов функции SuspendThread потоком, который имеет объект синхронизации, типа мьютекса (флажка блокировки) или критической секции, может привести к тупиковой ситуации, если вызывающий поток пробует получить объект синхронизации, принадлежащий приостановленному потоку. Чтобы избежать этой ситуации, поток в пределах прикладной программы, которое не является отладчиком, должен подать сигнал другому потоку, что приостановил себя. Целевой поток должен быть разработан, чтобы наблюдать за этим сигналом и соответственно реагировать.
И тут не все просто как хотелось бы. И, кстати, интересно какова скорость срабатывания такого suspend/resume

Элементарный юзкейс - например, вычисляете 10-ю потоками некое сложное значение, юзер ждет, но решает поставить операцию на паузу и выполнить другое жирное вычисление.
Неплохой пример, но все же надо заметить что "другое жирное" будет выполнено др нитками, хотя да, быстрее (нагрузку на ядра мы уменьшили)


Название: Re: ThreadControl suspend/resume/abort
Отправлено: AkonResumed от Октябрь 19, 2020, 22:55
Некросплатформенно, это Win API. Я привел пример, когда постановка потока на паузу оправдана, более того, этот функционал есть в Win API, системы, над которой работало не самое малое количество далеко не самых последних инженеров, - согласитесь, это имеет вес.

Скорость переключения? Cерьезно?.. ~ 2000 аccемблерных инструкций на x86 (переход в режим ядра), то же, что и у Sleep.


Название: Re: ThreadControl suspend/resume/abort
Отправлено: tux от Октябрь 19, 2020, 22:59
Некросплатформенно, это Win API.
Ну и на кой ляд оно в 2020 году? Тем более в Qt.


Название: Re: ThreadControl suspend/resume/abort
Отправлено: AkonResumed от Октябрь 20, 2020, 10:01
Я вовсе не агитирую за агульное применение! Просто проиллюстрировал, что подобный функционал (постановка потока на паузу) востребован.


Название: Re: ThreadControl suspend/resume/abort
Отправлено: Igors от Октябрь 20, 2020, 10:56
этот функционал есть в Win API, системы, над которой работало не самое малое количество далеко не самых последних инженеров, - согласитесь, это имеет вес.
Не разделяю восторгов по поводу Вын API, вынужден поддерживать эту платформу но это, пожалуй, одна из самых неприятных частей работы. Тем не менее, о возможности делать это "через ОС" не знал, спасибо

Я вовсе не агитирую за агульное применение! Просто проиллюстрировал, что подобный функционал (постановка потока на паузу) востребован.
Да. Далеко не всегда удается разделить задачу на (достаточно мелкие) "порционные куски" что могут выполняться любой ниткой. Это как бы "идеальный вариант" к которому надо стремиться.


Название: Re: ThreadControl suspend/resume/abort
Отправлено: tux от Октябрь 20, 2020, 13:40
Я вовсе не агитирую за агульное применение! Просто проиллюстрировал, что подобный функционал (постановка потока на паузу) востребован.
Огульное. :)
А то, что поток частенько желательно поставить на паузу и, приходится делать для этого дикие и не очень костыли - это да. Подтверждаю.


Название: Re: ThreadControl suspend/resume/abort
Отправлено: RedDog от Октябрь 20, 2020, 17:43
а какой нибудь std::condition_variable::wait() нельзя было заюзать?