Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.87/30: Рейтинг темы: голосов - 30, средняя оценка - 4.87
36 / 36 / 2
Регистрация: 28.04.2013
Сообщений: 110
1

Многопоточность, выход из бесконечного цикла c++11

03.06.2014, 23:06. Показов 5562. Ответов 70
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет. Я в задачах многопоточности - новичок (начал ей заниматься буквально несколько часов назад), инфу искал, читал, но как-то пока не помогает.

Столкнулся с задачей (с++11 std::thread) код не оригинальный, а упрощённый, чтобы показать саму суть, подразумевается, что все необходимые include'ы уже есть.

есть
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class SomeClass
{
private:
   bool _stopCycle;
public:
  void inifiniteWhile()
  {
      _stopCycle = false;
 
      while(!_stopCycle)
      {
          // do things ...
          // show window
      }
  }
 
   void stop() {_stopCycle = false;}
 
};
Main function

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
   SomeClass obj;
   thread someThread(&SomeClass::obj, infiniteCycle);
 
   while(/*read command from cmd*/)
   {
      if(cmd == exit)
      {
         obj.stop();
         break;
      }
   }
 
   system("pause");
}
Гарантируется, что из while(read cmd) программа выходит, т.е. я прихожу к system("pause");

Проблема: someThread не останавливает работу функции infinite. Цикл так и продолжает крутиться, выполняются do things и show window.
Вопрос: Как завершить цикл ?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.06.2014, 23:06
Ответы с готовыми решениями:

Выход из бесконечного цикла
Реально ли сделать выход из цикла без команды ввода? Допустим идет бесконечный цикл и в любой...

Выход из бесконечного цикла по нажатию кнопки.
Привет всем. как можно выйти из такого цикла по нажатию какой любой кнопки (например Esc) int...

Выход из бесконечного цикла
Помогите, пожалуйста, нужно выполнять цикл до тех пор, пока в консоли ничего не введут(то есть...

Выход из бесконечного цикла
Сегодня как дурачок создаю сотую тему, но все же прошу помощи. Есть программа, которая решает вот...

70
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
05.06.2014, 15:27 41
Author24 — интернет-сервис помощи студентам
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
Цитата Сообщение от Psilon Посмотреть сообщение
если вызывающему коду нужно вставлять задержки для корректной работы, то это хрень, а не многопоточное приложение.
Согласен, для этого я выложил второй код, без задержки. Задержка - это чтобы обозначить причину зацикливания.
Цитата Сообщение от Psilon Посмотреть сообщение
Не вижу беды в том, что Stop() будет вызван раньше, чем начнется поток
Если 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
Цитата Сообщение от alsav22 Посмотреть сообщение
Если stop() будет вызвана рашьше, то _stopCycle = true и выход из цикла в основном потоке, затем (если позже) следует заход в inifiniteWhile(), _stopCycle = false и заход в цикл, выход из которого возможен только если _stopCycle = true. Поздравляю с зацикливанием!
stop() должна присваивать значение, гарантирующее выход из цикла, а будучи вызванной до запуска потока, эта же функция должна присваивать тоже самое значение, но уже гарантировано предотвращающее старт цикла. Если же stop() присваивает значение, исключающее выход из цикла, то её вызов ни при каких условиях не приведёт к остановке потока, не зависимо от того, вызвана ли она после старта цикла, или же до. Не уподобляйтесь мелкомягким: не нарушайте логику приложения.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 15:55 45
taras atavin, вот код - 37 пост, вот зацикливание - скрин в 39 посте. Почему зацикливание, по-вашему, происходит?
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
05.06.2014, 16:05 46
1. Я уже предположил раздельные копии флага в первичном и вторичном потоках.
2. При вызове stop() до фактического начала исполнения void inifiniteWhile() логика приложения нарушена в части гарантии предотвращения старта цикла: флаг присваивается ещё раз, получая значение, при котором выход из цикла не возможен. Инициализация флага всё таки должна происходить до stop(), а не после, если возможен вызов stop() до фактического старта вторичного потока, инициировать флаг надо в первичном потоке.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 16:05 47
Цитата Сообщение от taras atavin Посмотреть сообщение
Я уже предположил раздельные копии флага в первичном и вторичном потоках.
Почему, если сделать паузу в основном потоке (мой первый код, во втором посте), раздельные копии флага перестают влиять на что-либо, и зацикливания не происходит?
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
05.06.2014, 16:14 48
А если флаг инициируется во вторичном потоке, то надо исключить вызов stop() до завершения первого шага цикла во вторичном потоке.

Добавлено через 4 минуты
Цитата Сообщение от alsav22 Посмотреть сообщение
Почему, если сделать паузу в основном потоке (мой первый код, во втором посте), раздельные копии флага перестают влиять на что-либо, и зацикливания не происходит?
Может быть раздельные копии в данном случае имеют место в кеше, но не в основной оперативной памяти и в некоторых случаях происходит рекогеренция кеша? Надо исключить саму возможность влияния декогеренции кеша на реактивность вторичного потока на команду завершения.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 16:15 49
Цитата Сообщение от taras atavin Посмотреть сообщение
А если флаг инициируется во вторичном потоке, то надо исключить вызов stop() до завершения первого шага цикла во вторичном потоке.
Хорошо, давайте вот такой код (инициализация _stopCycle будет происходить при создании объекта в основном потоке):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class SomeClass
{
    CRITICAL_SECTION gCS;
    volatile bool _stopCycle;
public:
    SomeClass()
    {
        InitializeCriticalSection(&gCS);
        _stopCycle = true;
 
    }
 
    ~SomeClass()
    {
        DeleteCriticalSection(&gCS);
    }
 
    void inifiniteWhile()   {
        if (_stopCycle)
        {
            EnterCriticalSection(&gCS);
            _stopCycle = false;
            LeaveCriticalSection(&gCS);
        }
        while (!_stopCycle)
        {
            cout << "inifiniteWhile" << endl;
        }
    }
 
    void stop() {
        if (!_stopCycle)
        {
            EnterCriticalSection(&gCS);
            _stopCycle = true;
            LeaveCriticalSection(&gCS);
        }
    }
};
 
int main(int argv, char* argc[])
{
    SomeClass obj;
    thread someThread(&SomeClass::inifiniteWhile, &obj);
    someThread.detach();
 
    while(true)
    {
        if(true)
        {
            obj.stop();
            break;
        }
    }
 
    system("pause");
    
    return 0;
}
Зацикливание. Если добавить паузу в основном потоке, зацикливания нет.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
05.06.2014, 16:22 50
Ещё смешней. Критикальная секция открывается на всё время существования объекьа, , исключая всякое влияние на вторичный поток из первичного. Самостоятельно получать информацию о событиях из системы он тоже не может по ограничениям, наложенным на вторичные потоки. И после этого будете ожидать, что он закроется?
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 16:24 51
Цитата Сообщение от taras atavin Посмотреть сообщение
Ещё смешней. Критикальная секция открывается на всё время работы вторичного потока, исключая всякое влияние на него из первичного. Самостоятельно получать информацию о событиях из системы он тоже не может по ограничениям, наложенным на вторичные потоки. И после этого будете ожидать, что он закроется?
Цитата Сообщение от alsav22 Посмотреть сообщение
Если добавить паузу в основном потоке, зацикливания нет.
Почему? Куда деваются "Критикальная секция" и прочее, при добавлении паузы?
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
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 17:08 54
Цитата Сообщение от taras atavin Посмотреть сообщение
А разве и в этом варианте существуют различно себя ведущие подварианты? ТС сообщил о влиянии паузы при инициировании флага вторичным потоком. Решите, должна ли stop() делать цикл не выполняемым, или именно завершать ранее запущенный цикл, отсюда и место инициирования флага, и вся связанная с ним логика.
Понятно, сказка про белого бычка...

Добавлено через 1 минуту
Цитата Сообщение от Somebody Посмотреть сообщение
Я только не понимаю, зачем создаваемый поток вообще изменяет флаг? Путь его дефолтный конструктор (явно объявленный) инициализирует в false, а основной поток ставит в true.
Всё правильно, но к теме не относится.
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
05.06.2014, 19:54 55
Цитата Сообщение от alsav22 Посмотреть сообщение
Я вам скрин выложил, как у меня работает (это когда stop() вызывается раньше). Всё равно: "не вижу беды"?
да, это эквивалентно отсутствию вызова stop(). Если мы жмем на тормоз до того, как машина поехала, мы же не жалуемся, что она не остановилась после того. как мы стартанули? То, что мы сначала нажали на тормоз, а потом на газ - это наши личные проблемы с отсутствием мозга, сама машина (то есть программа) реагирует совершенно правильно.
0
alsav22
05.06.2014, 20:03
  #56

Не по теме:

Этот бред о чём? Где и кто жмёт на газ? Может объяснишь, по какой причине, в этом коде, может быть такое:

Цитата Сообщение от Psilon Посмотреть сообщение
отсутствию вызова stop().

0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
05.06.2014, 20:25 57
Так смотря что за машина. Автомобиль не имеет комплексного интерфейса в связи с примитивностью исполнителя, а тормоз предназначен для остановки в случае, если раньше машина двигалась, но предполагает, что двигаться она могла и накатом, по инерции, или на буксире и дополнительно предназначен ля предотвращения начала движения, но может быть и отпущен. Программы не работают на буксире, по инерции и накатом, а исполняются на процессоре, претендующем на самостоятельную логику и должны иметь именно комплексные интерфейсы, а не комплекты разрозненных интерфейсов. Руль, педаль тормоза, педаль "газа", педаль сцепления, замок зажигания, кнопки управления фарами и "поворотниками" единого интерфейса не образуют, это только отдельные интерфейсы и не более и ни один канал управления не предоставляет доступа к памяти автомобиля, даже инкапсулированной, кроме простой инерции. Экранные кнопки гуёвого приложения, или команды приложения с текстовым интерфейсом - это не только отдельные интерфейсы, но совокупность всех кнопок одной панели - это тоже один составной интефейс, совокупность панелей одного окна - тоже один интерфейс, совокупность всех окон одного приложения - опять один интерфейс и так далее, вся командная строка со всей совокупностью команд - один интерфейс. И весь комплексный интерфейс приложения предоставляет доступ к памяти, пусть и не прямой. Поэтому кнопка "стоп" или вообще должна быть не активна, пока вторичный поток не начнёт работать, или же факт её нажатия должен запоминаться, блокируя "старт", пока не отожмёшь, а на текстовую команду "stop" до старта вторичного потока надо или писать что то вроде: "Данная команда не может быть исполнена, так как нечего останавливать", или предотвращать старт до явной отмены команды "stop" с интерфейса приложения. Вы же не удивляетесь, наличию кнопки "предыдущий канал" на пульте от телевизора? А комп ещё продвинутей в плане обработки логики машиной. Не удивляетесь, если на автомобиле с турбонаддувом движка не довернув ключ зажигания до стартера выключить зажигание и вытащить ключ турбина не запускается для плавного торможения и охлаждения? А почему комп должен быть тупее велосипеда? Если до запуска вторичного потока поступила команда полного закрытия, то он не должен запускаться, как и велосипед не примется сначала ехать, а потом тормозить, если педали провернуть сразу назад, а блокирует начало движения накатом, или при попытке катить его за руль, или раму, идя рядом. Пока не отпустишь тормоз, блокируется начало движения. Но если ты сначала отпустил тормоз, а потом потянул автомобиль другой машиной, то не обижайся, что она поедет. Или если сначала отпустил тормоз, а потом завёл двигатель и отжал сцепление. Не обижайся, что она сразу поедет. Тормоз то действовать перестал, он не запоминает предыдущие события и отменяется отпусканием педали.
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
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
Цитата Сообщение от Psilon Посмотреть сообщение
alsav22, taras atavin, stop() должен остановить поток, если он выполнялся, и ничего не делать, если поток не был запущен.
Нет. Автомобиль не должен сообщать о том, что водитель делает что то не то, ведь автомобиль - это самобеглая карета, какими бы прибамбасами вплоть до компьютеров он ни оснащался, это не меняет идею. А комп - это всё таки устройство, самостоятельно принимающее хоть какие то решения. Пусть даже в полностью формализованных ситуациях и заранее предусмотренные, но всё таки. Автомобиль задавит хоть хозяина, если остановиться на горке, забыть про стояночный тормоз, выйти и встать перед машиной. И это не будет следствием дефекта, потому что его водят вручную, комп же должен чётко исполнять приказы и не делать ничего лишнего, но при ошибочных действиях пользователя принято сообщать, что так делать не надо. Команду "рядом" от поводка отличаешь? Точно та же разница между командой пользователя компьютеру и верчением руля, давлением ног на педали "газа", сцепления и тормоза, нажатием кнопок управления фарами и "поворотниками". Поэтому функция не имеет права не делать ничего, будучи вызванной в определённой ситуации, а только являясь заглушкой на определённом этапе разработки. Или она должна предотвращать старт цикла во вторичном потоке, или до старта вообще не должна вызываться.

Добавлено через 6 минут
Цитата Сообщение от Psilon Посмотреть сообщение
Но тут уже зависит от предметной области и от практики использования исключений в компанде.
Только в симуляторе чего то столь же тупого, как автомобиль, можно не сообщать пользователю, что он делает что то не то, но и тогда кнопка то пусть нажмётся, а функция вызываться не должна, если только логика не вынесена прямо в обработчик, тогда если там простое присваивание, пусть выполнится в холостую, а если какая то последовательность действий по некому алгоритму, то пусть ограничится проверкой флага и завершится. А если стоп до старта - это не что то не то, значит это приказ не запускать вторичный поток и его тоже надо выполнить.
0
06.06.2014, 07:26
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.06.2014, 07:26
Помогаю со студенческими работами здесь

Выход из бесконечного цикла
я начинаю изучать PHP, задача такая: есть бесконечный цикл отправки POST запроса как сделать чтоб ...

Выход из бесконечного цикла
Здравствуйте Посмотрите вот такой интересный код s := 1; i := 1; repeat s := s/2; ...

Выход из бесконечного цикла
Как выйти из этого цикла при условии, что сгенерируется значение FAFZYMA2 while(true) ...

Выход из бесконечного цикла программно
Всем привет! Хочу сделать прогу дни рождения. Так вот вопрос такой подскажите как выходить из...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru