36 / 36 / 2
Регистрация: 28.04.2013
Сообщений: 110
|
|||||||||||
1 | |||||||||||
Многопоточность, выход из бесконечного цикла c++1103.06.2014, 23:06. Показов 5562. Ответов 70
Метки нет (Все метки)
Всем привет. Я в задачах многопоточности - новичок (начал ей заниматься буквально несколько часов назад), инфу искал, читал, но как-то пока не помогает.
Столкнулся с задачей (с++11 std::thread) код не оригинальный, а упрощённый, чтобы показать саму суть, подразумевается, что все необходимые include'ы уже есть. есть
Проблема: someThread не останавливает работу функции infinite. Цикл так и продолжает крутиться, выполняются do things и show window. Вопрос: Как завершить цикл ?
0
|
03.06.2014, 23:06 | |
Ответы с готовыми решениями:
70
Выход из бесконечного цикла Выход из бесконечного цикла по нажатию кнопки. Выход из бесконечного цикла Выход из бесконечного цикла |
Master of Orion
|
|
05.06.2014, 15:27 | 41 |
alsav22, если вызывающему коду нужно вставлять задержки для корректной работы, то это хрень, а не многопоточное приложение.
Не вижу беды в том, что Stop() будет вызван раньше, чем начнется поток - он и не обязан вызываться позже.
0
|
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
05.06.2014, 15:28 | 42 |
Поищите ка, где я хоть что то утверждаю про volatile.
0
|
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
|
|
05.06.2014, 15:41 | 43 |
Согласен, для этого я выложил второй код, без задержки. Задержка - это чтобы обозначить причину зацикливания.
Если stop() будет вызвана рашьше, то _stopCycle = true и выход из цикла в основном потоке, затем (если позже) следует заход в inifiniteWhile(), _stopCycle = false и заход в цикл, выход из которого возможен только если _stopCycle = true. Поздравляю с зацикливанием! Добавлено через 5 минут Я вам скрин выложил, как у меня работает (это когда stop() вызывается раньше). Всё равно: "не вижу беды"?
0
|
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
05.06.2014, 15:49 | 44 |
stop() должна присваивать значение, гарантирующее выход из цикла, а будучи вызванной до запуска потока, эта же функция должна присваивать тоже самое значение, но уже гарантировано предотвращающее старт цикла. Если же stop() присваивает значение, исключающее выход из цикла, то её вызов ни при каких условиях не приведёт к остановке потока, не зависимо от того, вызвана ли она после старта цикла, или же до. Не уподобляйтесь мелкомягким: не нарушайте логику приложения.
0
|
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
05.06.2014, 16:05 | 46 |
1. Я уже предположил раздельные копии флага в первичном и вторичном потоках.
2. При вызове stop() до фактического начала исполнения void inifiniteWhile() логика приложения нарушена в части гарантии предотвращения старта цикла: флаг присваивается ещё раз, получая значение, при котором выход из цикла не возможен. Инициализация флага всё таки должна происходить до stop(), а не после, если возможен вызов stop() до фактического старта вторичного потока, инициировать флаг надо в первичном потоке.
0
|
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
05.06.2014, 16:14 | 48 |
А если флаг инициируется во вторичном потоке, то надо исключить вызов stop() до завершения первого шага цикла во вторичном потоке.
Добавлено через 4 минуты Может быть раздельные копии в данном случае имеют место в кеше, но не в основной оперативной памяти и в некоторых случаях происходит рекогеренция кеша? Надо исключить саму возможность влияния декогеренции кеша на реактивность вторичного потока на команду завершения.
0
|
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
|
||||||
05.06.2014, 16:15 | 49 | |||||
Хорошо, давайте вот такой код (инициализация _stopCycle будет происходить при создании объекта в основном потоке):
0
|
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
05.06.2014, 16:22 | 50 |
Ещё смешней. Критикальная секция открывается на всё время существования объекьа, , исключая всякое влияние на вторичный поток из первичного. Самостоятельно получать информацию о событиях из системы он тоже не может по ограничениям, наложенным на вторичные потоки. И после этого будете ожидать, что он закроется?
0
|
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
05.06.2014, 16:33 | 52 |
А разве и в этом варианте существуют различно себя ведущие подварианты? ТС сообщил о влиянии паузы при инициировании флага вторичным потоком. Решите, должна ли stop() делать цикл не выполняемым, или именно завершать ранее запущенный цикл, отсюда и место инициирования флага, и вся связанная с ним логика.
0
|
2835 / 1644 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
|
|
05.06.2014, 16:51 | 53 |
Я только не понимаю, зачем создаваемый поток вообще изменяет флаг? Путь его дефолтный конструктор (явно объявленный) инициализирует в false, а основной поток ставит в true.
0
|
Master of Orion
|
|
05.06.2014, 19:54 | 55 |
да, это эквивалентно отсутствию вызова stop(). Если мы жмем на тормоз до того, как машина поехала, мы же не жалуемся, что она не остановилась после того. как мы стартанули? То, что мы сначала нажали на тормоз, а потом на газ - это наши личные проблемы с отсутствием мозга, сама машина (то есть программа) реагирует совершенно правильно.
0
|
alsav22
|
05.06.2014, 20:03
#56
|
0
|
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
05.06.2014, 20:25 | 57 |
Так смотря что за машина. Автомобиль не имеет комплексного интерфейса в связи с примитивностью исполнителя, а тормоз предназначен для остановки в случае, если раньше машина двигалась, но предполагает, что двигаться она могла и накатом, по инерции, или на буксире и дополнительно предназначен ля предотвращения начала движения, но может быть и отпущен. Программы не работают на буксире, по инерции и накатом, а исполняются на процессоре, претендующем на самостоятельную логику и должны иметь именно комплексные интерфейсы, а не комплекты разрозненных интерфейсов. Руль, педаль тормоза, педаль "газа", педаль сцепления, замок зажигания, кнопки управления фарами и "поворотниками" единого интерфейса не образуют, это только отдельные интерфейсы и не более и ни один канал управления не предоставляет доступа к памяти автомобиля, даже инкапсулированной, кроме простой инерции. Экранные кнопки гуёвого приложения, или команды приложения с текстовым интерфейсом - это не только отдельные интерфейсы, но совокупность всех кнопок одной панели - это тоже один составной интефейс, совокупность панелей одного окна - тоже один интерфейс, совокупность всех окон одного приложения - опять один интерфейс и так далее, вся командная строка со всей совокупностью команд - один интерфейс. И весь комплексный интерфейс приложения предоставляет доступ к памяти, пусть и не прямой. Поэтому кнопка "стоп" или вообще должна быть не активна, пока вторичный поток не начнёт работать, или же факт её нажатия должен запоминаться, блокируя "старт", пока не отожмёшь, а на текстовую команду "stop" до старта вторичного потока надо или писать что то вроде: "Данная команда не может быть исполнена, так как нечего останавливать", или предотвращать старт до явной отмены команды "stop" с интерфейса приложения. Вы же не удивляетесь, наличию кнопки "предыдущий канал" на пульте от телевизора? А комп ещё продвинутей в плане обработки логики машиной. Не удивляетесь, если на автомобиле с турбонаддувом движка не довернув ключ зажигания до стартера выключить зажигание и вытащить ключ турбина не запускается для плавного торможения и охлаждения? А почему комп должен быть тупее велосипеда? Если до запуска вторичного потока поступила команда полного закрытия, то он не должен запускаться, как и велосипед не примется сначала ехать, а потом тормозить, если педали провернуть сразу назад, а блокирует начало движения накатом, или при попытке катить его за руль, или раму, идя рядом. Пока не отпустишь тормоз, блокируется начало движения. Но если ты сначала отпустил тормоз, а потом потянул автомобиль другой машиной, то не обижайся, что она поедет. Или если сначала отпустил тормоз, а потом завёл двигатель и отжал сцепление. Не обижайся, что она сразу поедет. Тормоз то действовать перестал, он не запоминает предыдущие события и отменяется отпусканием педали.
0
|
Master of Orion
|
|
05.06.2014, 21:34 | 58 |
alsav22, taras atavin, stop() должен остановить поток, если он выполнялся, и ничего не делать, если поток не был запущен. А в какой последовательности что делать: сначала вызывать stop, а потом стартовать, или стартовать, подождать, нажать stop() или в какой-нибудь любой другой последовательности - дело вызывающего кода. Класс об этом не знает и знать не должен. Про это даже хитрое слово есть... как его... Инг... Инкоб... Инкапсуляция, во!
Добавлено через 1 минуту Хотя в идеальном вариант stop() для стоящего потока должен просто бросать исключение типа InvalidStateException. Но тут уже зависит от предметной области и от практики использования исключений в компанде.
0
|
alsav22
|
05.06.2014, 22:29
#59
|
Не по теме: Пора заканчивать. Все сказали, что смогли, или что посчитали нужным. ТС пропал, ему, видимо, на наши дебаты наплевать.
1
|
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
06.06.2014, 07:26 | 60 |
Нет. Автомобиль не должен сообщать о том, что водитель делает что то не то, ведь автомобиль - это самобеглая карета, какими бы прибамбасами вплоть до компьютеров он ни оснащался, это не меняет идею. А комп - это всё таки устройство, самостоятельно принимающее хоть какие то решения. Пусть даже в полностью формализованных ситуациях и заранее предусмотренные, но всё таки. Автомобиль задавит хоть хозяина, если остановиться на горке, забыть про стояночный тормоз, выйти и встать перед машиной. И это не будет следствием дефекта, потому что его водят вручную, комп же должен чётко исполнять приказы и не делать ничего лишнего, но при ошибочных действиях пользователя принято сообщать, что так делать не надо. Команду "рядом" от поводка отличаешь? Точно та же разница между командой пользователя компьютеру и верчением руля, давлением ног на педали "газа", сцепления и тормоза, нажатием кнопок управления фарами и "поворотниками". Поэтому функция не имеет права не делать ничего, будучи вызванной в определённой ситуации, а только являясь заглушкой на определённом этапе разработки. Или она должна предотвращать старт цикла во вторичном потоке, или до старта вообще не должна вызываться.
Добавлено через 6 минут Только в симуляторе чего то столь же тупого, как автомобиль, можно не сообщать пользователю, что он делает что то не то, но и тогда кнопка то пусть нажмётся, а функция вызываться не должна, если только логика не вынесена прямо в обработчик, тогда если там простое присваивание, пусть выполнится в холостую, а если какая то последовательность действий по некому алгоритму, то пусть ограничится проверкой флага и завершится. А если стоп до старта - это не что то не то, значит это приказ не запускать вторичный поток и его тоже надо выполнить.
0
|
06.06.2014, 07:26 | |
06.06.2014, 07:26 | |
Помогаю со студенческими работами здесь
60
Выход из бесконечного цикла Выход из бесконечного цикла Выход из бесконечного цикла Выход из бесконечного цикла программно Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |