К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как прервать цикл в 1С: операторы Прервать, Продолжить и Возврат

Как прервать цикл в 1С: операторы Прервать, Продолжить и Возврат, примеры кода для циклов Для, Пока и обхода коллекций, типичные ошибки и проверка результата.

Во встроенном языке 1С для управления выполнением циклов предусмотрены три оператора: Прервать, Продолжить и Возврат. Они работают во всех видах циклов — Для ... Цикл, Для Каждого ... Цикл и Пока ... Цикл — и позволяют досрочно завершить перебор, пропустить текущую итерацию или выйти из процедуры целиком.

Чаще всего цикл прерывают, когда нужный элемент уже найден и дальнейший перебор не имеет смысла: это ускоряет код и упрощает логику. Реже требуется пропустить часть итераций по условию — для этого служит оператор Продолжить. Важно понимать разницу между ними: Прервать завершает только цикл, а Возврат — всю процедуру или функцию, что при неосторожном использовании приводит к потере данных или пропуску важных действий.

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

Оператор Прервать: досрочный выход из цикла

Оператор Прервать немедленно завершает выполнение ближайшего цикла, внутри которого он находится, и передаёт управление первой строке после ключевого слова КонецЦикла. Код, записанный после Прервать внутри тела цикла, в текущей итерации не выполняется.

Типовой сценарий — поиск элемента в коллекции. Как только элемент найден, дальнейший перебор бессмысленен, и цикл прерывают:

НайденныйСотрудник = Неопределено;

Для Каждого Сотрудник Из ТаблицаСотрудников Цикл

Если Сотрудник.ТабельныйНомер = ИскомыйНомер Тогда

НайденныйСотрудник = Сотрудник;

Прервать;

КонецЕсли;

КонецЦикла;

Обратите внимание на приём с переменной-флагом НайденныйСотрудник: после цикла по её значению легко понять, был ли элемент найден. Если переменная осталась равной Неопределено, значит, цикл завершился естественным образом, не найдя совпадения. Это надёжнее, чем проверять, «сработал ли Прервать».

Оператор Прервать можно вызывать безусловно, но на практике он почти всегда стоит внутри условия Если. Безусловный Прервать в начале цикла фактически превращает его в однократное выполнение тела — обычно это признак ошибки в логике.

Оператор Продолжить: пропуск текущей итерации

Оператор Продолжить не завершает цикл, а досрочно заканчивает текущую итерацию: весь код ниже него в теле цикла пропускается, и начинается следующий проход. Для цикла Для при этом счётчик увеличивается, для Для Каждого берётся следующий элемент коллекции, для Пока заново проверяется условие.

Классическое применение — фильтрация: пропустить элементы, которые не подходят под условие обработки.

Для Каждого Строка Из ТаблицаТоваров Цикл

Если Строка.Количество = 0 Тогда

Продолжить; // нулевые строки не обрабатываем

КонецЕсли;

Если Строка.ПометкаУдаления Тогда

Продолжить;

КонецЕсли;

// основная обработка строки

РассчитатьСкидку(Строка);

КонецЦикла;

Такой стиль с «ранними выходами» через Продолжить делает код плоским и читаемым: вместо глубокой вложенности Если ... Тогда ... КонецЕсли условия-исключения выносятся в начало итерации. Это общепринятая практика, которую рекомендуют стандарты разработки на платформе 1С.

Не путайте Продолжить и Прервать: если по ошибке написать Прервать вместо Продолжить, цикл обработает только часть коллекции до первого «неподходящего» элемента. Симптом такой ошибки — в обработку попадает меньше строк, чем ожидалось, при этом явного сообщения об ошибке нет.

Сравнение операторов управления циклом

Прервать

Полностью завершает ближайший цикл. Подходит, когда результат найден и дальнейший перебор не нужен.

Продолжить

Пропускает остаток текущей итерации и переходит к следующей. Подходит для фильтрации элементов.

Возврат

Завершает всю процедуру или функцию. Подходит, когда после цикла ничего выполнять не требуется.

Оператор Возврат: выход из процедуры внутри цикла

Оператор Возврат завершает выполнение всей процедуры или функции, а не только цикла. В функции после Возврат указывается возвращаемое значение. Если после цикла в процедуре нет другого кода, Возврат внутри цикла фактически заменяет Прервать, но семантически это разные действия.

Функция НайтиДокументПоНомеру(Номер)

Для Каждого Док Из СписокДокументов Цикл

Если Док.Номер = Номер Тогда

Возврат Док; // выходим из функции сразу с результатом

КонецЕсли;

КонецЦикла;

Возврат Неопределено;

КонецФункции

Главный риск Возврат внутри цикла — пропуск обязательных завершающих действий: закрытия транзакции, освобождения блокировки, записи журнала. Если такие действия есть, либо используйте Прервать и выполняйте завершение после цикла, либо оборачивайте код в Попытка ... Исключение ... КонецПопытки с корректной обработкой.

Прерывание вложенных циклов

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

Первый приём — переменная-флаг, которую проверяет внешний цикл:

НужноПрервать = Ложь;

Для Каждого Заказ Из Заказы Цикл

Для Каждого Строка Из Заказ.Товары Цикл

Если Строка.Сумма > Лимит Тогда

НужноПрервать = Истина;

Прервать; // выход из внутреннего цикла

КонецЕсли;

КонецЦикла;

Если НужноПрервать Тогда

Прервать; // выход из внешнего цикла

КонецЕсли;

КонецЦикла;

Второй приём — вынести перебор в отдельную функцию и использовать Возврат: он завершает функцию независимо от глубины вложенности циклов. Этот вариант чище, когда логика поиска самостоятельна и возвращает конкретный результат.

Как прервать вложенный цикл полностью
  1. 1
    Объявите перед внешним циклом переменную-флаг, например НужноПрервать = Ложь
  2. 2
    Внутри внутреннего цикла при срабатывании условия установите флаг в Истина и выполните Прервать
  3. 3
    Сразу после внутреннего цикла проверьте флаг: Если НужноПрервать Тогда Прервать
  4. 4
    Либо вынесите оба цикла в функцию и используйте Возврат с результатом
  5. 5
    Проверьте на тестовых данных, что обработка останавливается на нужном элементе

Прерывание цикла Пока и защита от бесконечного цикла

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

НомерПопытки = 0;

Пока Истина Цикл

НомерПопытки = НомерПопытки + 1;

Если ВыполнитьОбменДанными() Тогда

Прервать; // обмен успешен — выходим

КонецЕсли;

Если НомерПопытки >= 5 Тогда

Прервать; // защита от бесконечного цикла

КонецЕсли;

КонецЦикла;

Конструкция Пока Истина Цикл допустима только при наличии гарантированного выхода через Прервать. Если условие прерывания зависит от внешних данных (ответ сервера, результат запроса), обязательно добавляйте ограничение по числу итераций или по времени. Бесконечный цикл в серверном коде приводит к зависанию сеанса, а в фоновом задании — к бесполезному расходу ресурсов сервера до принудительного снятия задачи администратором.

Признак зависшего бесконечного цикла на клиенте — интерфейс перестаёт отвечать, в диспетчере задач растёт загрузка процессора процессом 1cv8. На сервере зависший сеанс виден в консоли кластера по длительному времени текущего вызова.

Контрольные точки

Как проверить, что прерывание работает правильно

Количество обработанных элементов
Норма

Обработаны все элементы до найденного, остальные пропущены

Тревожный признак

Обработан только первый элемент или, наоборот, вся коллекция целиком

Поведение при отсутствии результата
Норма

Цикл завершается естественно, переменная результата остаётся пустой, ошибок нет

Тревожный признак

После цикла код обращается к ненайденному элементу и падает с ошибкой

Цикл Пока с внешним условием
Норма

При недостижимом условии цикл останавливается по счётчику попыток

Тревожный признак

Сеанс зависает, растёт загрузка процессора

Типичные ошибки при прерывании циклов

Первая распространённая ошибка — использование результата после цикла без проверки, был ли он найден. Если Прервать не сработал ни разу, переменная остаётся в исходном состоянии, и обращение к ней как к найденному объекту вызывает ошибку. Всегда проверяйте результат: Если НайденныйСотрудник <> Неопределено Тогда ....

Вторая ошибка — изменение коллекции во время её перебора через Для Каждого. Удаление или добавление элементов в обходимую коллекцию приводит к непредсказуемому поведению или ошибке. Если нужно удалять элементы, обходите коллекцию индексным циклом Для с конца (с убыванием индекса) либо собирайте элементы на удаление в отдельный массив и удаляйте после цикла.

Третья ошибка — ожидание, что Прервать выйдет из всех вложенных циклов сразу. Как показано выше, оператор действует только на ближайший цикл. Четвёртая типичная ситуация — Продолжить в цикле Пока, где изменение переменной условия стоит после Продолжить: условие никогда не изменится, и цикл станет бесконечным. В циклах Пока следите, чтобы шаг изменения условия выполнялся до любого Продолжить.

Типичные ошибки
01
Прервать вместо Продолжить — цикл останавливается на первом неподходящем элементе, часть данных не обрабатывается
02
Использование результата поиска без проверки на Неопределено — ошибка выполнения, если элемент не найден
03
Удаление элементов коллекции внутри Для Каждого — пропуск элементов или ошибка обхода
04
Продолжить в цикле Пока до изменения переменной условия — бесконечный цикл и зависание сеанса
05
Возврат внутри цикла с открытой транзакцией — незавершённая транзакция и блокировки

Проверка результата и отладка

Убедиться, что прерывание работает как задумано, проще всего в отладчике конфигуратора. Установите точку останова на строке с Прервать и на первой строке после КонецЦикла: при запуске вы увидите, срабатывает ли условие прерывания и на каком элементе. В табло выражений добавьте переменную-счётчик цикла и переменную-результат, чтобы контролировать, сколько итераций реально выполнено.

Для прикладного кода полезно временно добавить счётчик обработанных элементов и вывести его через Сообщить() или в журнал регистрации. Если фактическое число итераций меньше ожидаемого — ищите лишний Прервать; если равно размеру коллекции там, где поиск должен был завершиться раньше — условие прерывания не срабатывает, проверяйте сравнение значений (частая причина — сравнение строк разной длины с пробелами или разным регистром).

После изменения логики прогоните код на граничных случаях: пустая коллекция, один элемент, искомый элемент первым, искомый элемент последним, искомого элемента нет. Эти пять сценариев покрывают практически все ошибки, связанные с досрочным выходом из цикла.

Итог

Что важно запомнить

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

Частые вопросы

Чем Прервать отличается от Возврат внутри цикла?

Прервать завершает только цикл, и выполнение продолжается со строки после КонецЦикла. Возврат завершает всю процедуру или функцию целиком — код после цикла в ней уже не выполнится. Если после цикла есть завершающие действия (запись, закрытие транзакции), используйте Прервать.

Как выйти сразу из двух вложенных циклов?

Одним оператором это сделать нельзя: Прервать действует только на ближайший цикл. Используйте переменную-флаг, которую внутренний цикл устанавливает перед Прервать, а внешний проверяет после него. Альтернатива — вынести перебор в функцию и выйти из неё через Возврат.

Работает ли Прервать при обходе выборки из запроса?

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

Можно ли удалять элементы коллекции внутри цикла?

В цикле Для Каждого удалять элементы обходимой коллекции нельзя — это приводит к ошибке или пропуску элементов. Удаляйте через индексный цикл Для с обходом с конца (от последнего индекса к первому) либо соберите удаляемые элементы в отдельный массив и удалите их после завершения основного цикла.

Что делать, если цикл в 1С завис и не завершается?

Скорее всего, это бесконечный цикл Пока: условие не меняется внутри тела цикла. На клиенте сеанс придётся завершить через диспетчер задач, на сервере — завершить сеанс через консоль кластера. В коде добавьте счётчик итераций с Прервать по достижении лимита и проверьте, что переменная условия изменяется до любого Продолжить.

Есть ли в 1С аналог меток или goto для выхода из цикла?

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