Разработка и Конфигурация · 9 мин
1С: как выйти из цикла «Пока»
Как выйти из цикла Пока в 1С: операторы Прервать, Продолжить, Возврат, правильное условие цикла и защита от бесконечного цикла. Примеры кода и типичные ошибки.
Цикл «Пока» во встроенном языке 1С выполняет тело цикла до тех пор, пока истинно условие, указанное в заголовке. Выйти из него можно двумя способами: дождаться, пока условие станет ложным, либо принудительно завершить итерации оператором Прервать или Возврат. Выбор способа зависит от логики задачи: где-то достаточно корректного условия, а где-то без досрочного выхода код получится громоздким и медленным.
Оператор Прервать немедленно останавливает выполнение цикла и передаёт управление на первую строку после ключевого слова КонецЦикла. Оператор Возврат выходит не только из цикла, но и из всей процедуры или функции целиком. Путать их нельзя: замена одного другим меняет поведение программы и часто приводит к неочевидным ошибкам в обработках.
Отдельная опасность — бесконечный цикл, когда условие никогда не становится ложным. Тогда сеанс 1С зависает, а в клиент-серверном режиме нагружается сервер. Ниже разобраны все способы выхода, защита от зависания и типичные ошибки разработчиков.
Как устроен цикл «Пока» и когда он завершается сам
Конструкция выглядит так: Пока Условие Цикл ... КонецЦикла;. Перед каждой итерацией платформа вычисляет условие. Если оно истинно — выполняется тело цикла, если ложно — цикл завершается, и выполнение продолжается со строки после КонецЦикла. Условие проверяется до входа в тело, поэтому цикл «Пока» может не выполниться ни разу, если условие ложно с самого начала.
Классический пример — обход выборки из запроса:
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Номенклатура);
КонецЦикла;
Здесь метод Следующий() возвращает Истина, пока есть необработанные строки, и Ложь, когда выборка исчерпана. Цикл завершается сам, без всяких дополнительных операторов. Это самый надёжный и читаемый вариант — если условие естественным образом описывает окончание работы, дополнительные прерывания не нужны.
Оператор «Прервать» — досрочный выход из цикла
Оператор Прервать используется, когда дальнейшие итерации бессмысленны: нужное значение уже найдено, обнаружена ошибка или выполнено условие остановки. После Прервать выполняется код, следующий за КонецЦикла.
Найден = Ложь;
Пока Выборка.Следующий() Цикл
Если Выборка.Артикул = ИскомыйАртикул Тогда
Найден = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
В этом примере нет смысла перебирать остальные строки выборки после нахождения нужного артикула — Прервать экономит время выполнения. На больших выборках разница заметна: без прерывания цикл прошёл бы все строки до конца.
Важно понимать: Прервать останавливает только тот цикл, внутри которого он записан. Если циклы вложенные, прервётся внутренний, а внешний продолжит работу. Для выхода сразу из нескольких уровней вложенности используют флаг-переменную или оператор Возврат.
- 1Объявите переменную-флаг, например НужноПрервать = Ложь, перед внешним циклом
- 2Во внутреннем цикле при выполнении условия установите флаг в Истина и выполните Прервать
- 3Во внешнем цикле после внутреннего проверьте флаг: Если НужноПрервать Тогда Прервать; КонецЕсли
- 4Проверьте, что после выхода выполняется нужный код, а переменные имеют ожидаемые значения
Оператор «Продолжить» — пропуск итерации, а не выход
Начинающие разработчики иногда путают Продолжить и Прервать. Оператор Продолжить не выходит из цикла — он лишь досрочно завершает текущую итерацию и переходит к проверке условия для следующей. Всё, что записано в теле цикла после Продолжить, в этой итерации не выполнится.
Пока Выборка.Следующий() Цикл
Если Выборка.ПометкаУдаления Тогда
Продолжить; // пропускаем помеченные на удаление
КонецЕсли;
ОбработатьСтроку(Выборка);
КонецЦикла;
Это удобно для фильтрации «неподходящих» строк без глубокой вложенности условий. Но если ваша цель — полностью остановить цикл, Продолжить не подходит: цикл будет крутиться дальше.
Сравнение способов выхода
Останавливает текущий цикл, выполнение продолжается после КонецЦикла. Подходит для досрочного завершения поиска или обработки.
Пропускает остаток текущей итерации и переходит к следующей. Цикл не завершается — используется для фильтрации элементов.
Выходит из всей процедуры или функции, включая все вложенные циклы. Подходит, когда после выхода из цикла делать в процедуре больше нечего.
Присвоение переменной условия значения Ложь внутри тела. Цикл завершится после текущей итерации — самый «мягкий» вариант.
Оператор «Возврат» — выход из цикла вместе с процедурой
Если после нахождения результата в процедуре или функции больше ничего не выполняется, проще сразу написать Возврат. В функции при этом обычно возвращают найденное значение:
Функция НайтиКонтрагентаПоИНН(ИНН)
Пока Выборка.Следующий() Цикл
Если Выборка.ИНН = ИНН Тогда
Возврат Выборка.Ссылка;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции;
Такой код короче и понятнее, чем связка «флаг + Прервать + проверка после цикла». Но помните об ограничении: Возврат прерывает всю процедуру. Если после цикла нужно освободить ресурсы, закрыть файл или зафиксировать транзакцию — эти действия не выполнятся. В таких случаях используйте Прервать, а общий код завершения размещайте после цикла.
Защита от бесконечного цикла
Бесконечный цикл возникает, когда условие никогда не становится ложным. Типичные причины: забыли изменить переменную-счётчик внутри тела, метод обхода данных всегда возвращает Истина, условие сформулировано с ошибкой в логике. Симптомы — зависший клиент, 100% загрузка процессора rphost на сервере, невозможность прервать операцию штатно.
Надёжная практика — добавить счётчик-ограничитель, если есть малейшее сомнение в условии:
Счетчик = 0;
Пока ЕстьДанныеДляОбработки() Цикл
Счетчик = Счетчик + 1;
Если Счетчик > 1000000 Тогда
ВызватьИсключение "Превышен лимит итераций цикла";
КонецЕсли;
// ... обработка
КонецЦикла;
Ещё одна мера — всегда проверять, что переменная, участвующая в условии, реально изменяется внутри тела. Если условие зависит от результата запроса или внешнего вызова, убедитесь, что данные меняются между итерациями, иначе цикл никогда не закончится.
Выбор между «Пока», «Для» и обходом коллекции
Цикл «Пока» оправдан, когда число итераций заранее неизвестно: обход выборки запроса, чтение файла до конца, ожидание наступления события. Если известно количество повторений или нужен индекс элемента — логичнее цикл Для. Для перебора всех элементов коллекции без условий — Для Каждого.
Способы выхода у всех циклов одинаковые: Прервать, Продолжить и Возврат работают в «Пока», «Для» и «Для Каждого» одинаково. Поэтому выбор конструкции влияет только на читаемость и удобство, но не на механику прерывания.
Частые вопросы о выходе из цикла «Пока»
Чем «Прервать» отличается от «Возврат» внутри цикла?
«Прервать» завершает только цикл, и код после «КонецЦикла» продолжает выполняться. «Возврат» завершает всю процедуру или функцию целиком — никакой код после цикла уже не выполнится. Выбирайте «Возврат», только если после цикла делать нечего.
Как выйти сразу из двух вложенных циклов «Пока»?
Штатного оператора многоуровнего прерывания в 1С нет. Используйте переменную-флаг: во внутреннем цикле установите её и выполните «Прервать», а во внешнем проверьте флаг и тоже выполните «Прервать». Альтернатива — «Возврат», если вся логика находится в отдельной функции.
Почему цикл «Пока» зависает и не завершается?
Почти всегда причина в том, что условие никогда не становится ложным: переменная-счётчик не меняется в теле цикла, метод обхода всегда возвращает Истина или в логике условия ошибка. Добавьте счётчик-ограничитель итераций с генерацией исключения — это поможет найти проблемное место при отладке.
Можно ли выйти из цикла по нажатию кнопки пользователем?
В синхронном коде толстого или тонкого клиента цикл блокирует интерфейс, и нажать кнопку пользователь не сможет. Для длительных операций используйте фоновые задания или обработчики ожидания, где прерывание проверяется между итерациями через переменную или метод, доступный из другого обработчика.
Работает ли «Прервать» в циклах «Для» и «Для Каждого»?
Да, операторы «Прервать», «Продолжить» и «Возврат» работают одинаково во всех видах циклов встроенного языка 1С: «Пока», «Для» и «Для Каждого». Синтаксис и поведение полностью совпадают.
Что важно запомнить
Досрочный выход из цикла «Пока» — оператор «Прервать», пропуск итерации — «Продолжить», выход из всей процедуры — «Возврат». Следите, чтобы условие цикла гарантированно становилось ложным, а при сомнениях добавляйте счётчик-ограничитель итераций. Для вложенных циклов используйте флаг-переменную или «Возврат».