Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.67
el_gato_de_Ch
35 / 35 / 1
Регистрация: 28.04.2013
Сообщений: 110
#1

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

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

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

Столкнулся с задачей (с++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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.06.2014, 23:06
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Многопоточность, выход из бесконечного цикла c++11 (C++):

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

Выход из бесконечного цыкла - C++
Проблема с выходом из бесконечного цикла. Если для выхода вводить exit, программа виснет и бесконечно выводит, то, что записано в cout....

Отладка бесконечного цикла - C++
Здравствуйте. Проблема такая, написал цикл программы взаимодействия пользователя с меню Цикл не имеет условия выхода, что бы выйти...

не работает проверка бесконечного цикла - C++
// разработать класс Student, который содержит соответствующие поля для хранения: // * фамилии,+ // * имени,+ // * отчества,+ // *...

Способы остановки бесконечного while цикла - C++
У меня такой вопрос: вот например у нас есть бесконечный цикл while с условиями while(true) { if(..){...} else(...){...}///и так...

Выход из цикла - C++
Есть цикл. Он выполняется. Долго. Пока он выполняется я нажимаю Esc и он становится на паузу. Как осуществить? Добавлено через 10...

70
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
05.06.2014, 16:05 #46
1. Я уже предположил раздельные копии флага в первичном и вторичном потоках.
2. При вызове stop() до фактического начала исполнения void inifiniteWhile() логика приложения нарушена в части гарантии предотвращения старта цикла: флаг присваивается ещё раз, получая значение, при котором выход из цикла не возможен. Инициализация флага всё таки должна происходить до stop(), а не после, если возможен вызов stop() до фактического старта вторичного потока, инициировать флаг надо в первичном потоке.
0
alsav22
5425 / 4820 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 16:05 #47
Цитата Сообщение от taras atavin Посмотреть сообщение
Я уже предположил раздельные копии флага в первичном и вторичном потоках.
Почему, если сделать паузу в основном потоке (мой первый код, во втором посте), раздельные копии флага перестают влиять на что-либо, и зацикливания не происходит?
0
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
05.06.2014, 16:14 #48
А если флаг инициируется во вторичном потоке, то надо исключить вызов stop() до завершения первого шага цикла во вторичном потоке.

Добавлено через 4 минуты
Цитата Сообщение от alsav22 Посмотреть сообщение
Почему, если сделать паузу в основном потоке (мой первый код, во втором посте), раздельные копии флага перестают влиять на что-либо, и зацикливания не происходит?
Может быть раздельные копии в данном случае имеют место в кеше, но не в основной оперативной памяти и в некоторых случаях происходит рекогеренция кеша? Надо исключить саму возможность влияния декогеренции кеша на реактивность вторичного потока на команду завершения.
0
alsav22
5425 / 4820 / 442
Регистрация: 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
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
05.06.2014, 16:22 #50
Ещё смешней. Критикальная секция открывается на всё время существования объекьа, , исключая всякое влияние на вторичный поток из первичного. Самостоятельно получать информацию о событиях из системы он тоже не может по ограничениям, наложенным на вторичные потоки. И после этого будете ожидать, что он закроется?
0
alsav22
5425 / 4820 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 16:24 #51
Цитата Сообщение от taras atavin Посмотреть сообщение
Ещё смешней. Критикальная секция открывается на всё время работы вторичного потока, исключая всякое влияние на него из первичного. Самостоятельно получать информацию о событиях из системы он тоже не может по ограничениям, наложенным на вторичные потоки. И после этого будете ожидать, что он закроется?
Цитата Сообщение от alsav22 Посмотреть сообщение
Если добавить паузу в основном потоке, зацикливания нет.
Почему? Куда деваются "Критикальная секция" и прочее, при добавлении паузы?
0
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
05.06.2014, 16:33 #52
А разве и в этом варианте существуют различно себя ведущие подварианты? ТС сообщил о влиянии паузы при инициировании флага вторичным потоком. Решите, должна ли stop() делать цикл не выполняемым, или именно завершать ранее запущенный цикл, отсюда и место инициирования флага, и вся связанная с ним логика.
0
Somebody
2791 / 1602 / 147
Регистрация: 03.12.2007
Сообщений: 4,197
Завершенные тесты: 1
05.06.2014, 16:51 #53
Я только не понимаю, зачем создаваемый поток вообще изменяет флаг? Путь его дефолтный конструктор (явно объявленный) инициализирует в false, а основной поток ставит в true.
0
alsav22
5425 / 4820 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
05.06.2014, 17:08 #54
Цитата Сообщение от taras atavin Посмотреть сообщение
А разве и в этом варианте существуют различно себя ведущие подварианты? ТС сообщил о влиянии паузы при инициировании флага вторичным потоком. Решите, должна ли stop() делать цикл не выполняемым, или именно завершать ранее запущенный цикл, отсюда и место инициирования флага, и вся связанная с ним логика.
Понятно, сказка про белого бычка...

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

Не по теме:

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

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

0
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
05.06.2014, 20:25 #57
Так смотря что за машина. Автомобиль не имеет комплексного интерфейса в связи с примитивностью исполнителя, а тормоз предназначен для остановки в случае, если раньше машина двигалась, но предполагает, что двигаться она могла и накатом, по инерции, или на буксире и дополнительно предназначен ля предотвращения начала движения, но может быть и отпущен. Программы не работают на буксире, по инерции и накатом, а исполняются на процессоре, претендующем на самостоятельную логику и должны иметь именно комплексные интерфейсы, а не комплекты разрозненных интерфейсов. Руль, педаль тормоза, педаль "газа", педаль сцепления, замок зажигания, кнопки управления фарами и "поворотниками" единого интерфейса не образуют, это только отдельные интерфейсы и не более и ни один канал управления не предоставляет доступа к памяти автомобиля, даже инкапсулированной, кроме простой инерции. Экранные кнопки гуёвого приложения, или команды приложения с текстовым интерфейсом - это не только отдельные интерфейсы, но совокупность всех кнопок одной панели - это тоже один составной интефейс, совокупность панелей одного окна - тоже один интерфейс, совокупность всех окон одного приложения - опять один интерфейс и так далее, вся командная строка со всей совокупностью команд - один интерфейс. И весь комплексный интерфейс приложения предоставляет доступ к памяти, пусть и не прямой. Поэтому кнопка "стоп" или вообще должна быть не активна, пока вторичный поток не начнёт работать, или же факт её нажатия должен запоминаться, блокируя "старт", пока не отожмёшь, а на текстовую команду "stop" до старта вторичного потока надо или писать что то вроде: "Данная команда не может быть исполнена, так как нечего останавливать", или предотвращать старт до явной отмены команды "stop" с интерфейса приложения. Вы же не удивляетесь, наличию кнопки "предыдущий канал" на пульте от телевизора? А комп ещё продвинутей в плане обработки логики машиной. Не удивляетесь, если на автомобиле с турбонаддувом движка не довернув ключ зажигания до стартера выключить зажигание и вытащить ключ турбина не запускается для плавного торможения и охлаждения? А почему комп должен быть тупее велосипеда? Если до запуска вторичного потока поступила команда полного закрытия, то он не должен запускаться, как и велосипед не примется сначала ехать, а потом тормозить, если педали провернуть сразу назад, а блокирует начало движения накатом, или при попытке катить его за руль, или раму, идя рядом. Пока не отпустишь тормоз, блокируется начало движения. Но если ты сначала отпустил тормоз, а потом потянул автомобиль другой машиной, то не обижайся, что она поедет. Или если сначала отпустил тормоз, а потом завёл двигатель и отжал сцепление. Не обижайся, что она сразу поедет. Тормоз то действовать перестал, он не запоминает предыдущие события и отменяется отпусканием педали.
0
Psilon
Master of Orion
Эксперт .NET
5902 / 4799 / 634
Регистрация: 10.07.2011
Сообщений: 14,407
Записей в блоге: 5
Завершенные тесты: 4
05.06.2014, 21:34 #58
alsav22, taras atavin, stop() должен остановить поток, если он выполнялся, и ничего не делать, если поток не был запущен. А в какой последовательности что делать: сначала вызывать stop, а потом стартовать, или стартовать, подождать, нажать stop() или в какой-нибудь любой другой последовательности - дело вызывающего кода. Класс об этом не знает и знать не должен. Про это даже хитрое слово есть... как его... Инг... Инкоб... Инкапсуляция, во!

Добавлено через 1 минуту
Хотя в идеальном вариант stop() для стоящего потока должен просто бросать исключение типа InvalidStateException. Но тут уже зависит от предметной области и от практики использования исключений в компанде.
0
alsav22
05.06.2014, 22:29
  #59

Не по теме:

Пора заканчивать. Все сказали, что смогли, или что посчитали нужным. ТС пропал, ему, видимо, на наши дебаты наплевать.

1
taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
06.06.2014, 07:26 #60
Цитата Сообщение от Psilon Посмотреть сообщение
alsav22, taras atavin, stop() должен остановить поток, если он выполнялся, и ничего не делать, если поток не был запущен.
Нет. Автомобиль не должен сообщать о том, что водитель делает что то не то, ведь автомобиль - это самобеглая карета, какими бы прибамбасами вплоть до компьютеров он ни оснащался, это не меняет идею. А комп - это всё таки устройство, самостоятельно принимающее хоть какие то решения. Пусть даже в полностью формализованных ситуациях и заранее предусмотренные, но всё таки. Автомобиль задавит хоть хозяина, если остановиться на горке, забыть про стояночный тормоз, выйти и встать перед машиной. И это не будет следствием дефекта, потому что его водят вручную, комп же должен чётко исполнять приказы и не делать ничего лишнего, но при ошибочных действиях пользователя принято сообщать, что так делать не надо. Команду "рядом" от поводка отличаешь? Точно та же разница между командой пользователя компьютеру и верчением руля, давлением ног на педали "газа", сцепления и тормоза, нажатием кнопок управления фарами и "поворотниками". Поэтому функция не имеет права не делать ничего, будучи вызванной в определённой ситуации, а только являясь заглушкой на определённом этапе разработки. Или она должна предотвращать старт цикла во вторичном потоке, или до старта вообще не должна вызываться.

Добавлено через 6 минут
Цитата Сообщение от Psilon Посмотреть сообщение
Но тут уже зависит от предметной области и от практики использования исключений в компанде.
Только в симуляторе чего то столь же тупого, как автомобиль, можно не сообщать пользователю, что он делает что то не то, но и тогда кнопка то пусть нажмётся, а функция вызываться не должна, если только логика не вынесена прямо в обработчик, тогда если там простое присваивание, пусть выполнится в холостую, а если какая то последовательность действий по некому алгоритму, то пусть ограничится проверкой флага и завершится. А если стоп до старта - это не что то не то, значит это приказ не запускать вторичный поток и его тоже надо выполнить.
0
06.06.2014, 07:26
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.06.2014, 07:26
Привет! Вот еще темы с ответами:

Выход из цикла - C++
Ув. программисты я пишу крестики-нолики, но возникла некоторая проблема с циклами! for (t=0;t&lt;100;t++) { for...

Выход из цикла - C++
Доброго времени суток. Подскажите, пожалуйста как сделать выход из цикла при нажатии 0 в меню. Пытался так на ESC, но не выходит. ...

С++ Выход из цикла - C++
Есть цикл, написанный в дополнительной функции. Нужно вывести сумму нескольких введенных чисел, если подходящей суммы нет,то вывести...

Принудительный выход из цикла - C++
Вообщем надо при определенном условии завершать вложенный цикл, такой код будет работать??? for(.....) { for(.....) { if...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru