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

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

Как прервать выполнение цикла в 1С

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

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

Операторы работают одинаково во всех видах циклов: Для ... Цикл, Для Каждого ... Цикл и Пока ... Цикл. Синтаксис не зависит от того, выполняется код на клиенте или на сервере, в тонком клиенте или в веб-клиенте.

Ниже разобраны все три оператора с примерами кода, особенности работы во вложенных циклах, типичные ошибки и способы проверить, что прерывание сработало так, как задумано.

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

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

Типичный сценарий — поиск нужного элемента в коллекции. Как только элемент найден, дальнейший перебор бессмысленен, и цикл следует остановить, чтобы не тратить время на оставшиеся итерации.

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

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

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

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

Прервать;

КонецЕсли;

КонецЦикла;

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

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

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

Это удобно для фильтрации: когда часть элементов коллекции обрабатывать не нужно, их проще «отсечь» в начале итерации, чем оборачивать всю логику в глубокие вложенные условия.

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

Если Не Строка.Проведен Тогда

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

КонецЕсли;

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

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

КонецЕсли;

// основная обработка только «подходящих» строк

ОбработатьСтроку(Строка);

КонецЦикла;

Такой стиль называют «ранним выходом»: условия-исключения выносятся в начало итерации, а основной код остаётся на верхнем уровне вложенности и читается легче.

Оператор «Возврат»: выход из процедуры вместе с циклом

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

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

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

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

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

КонецЕсли;

КонецЦикла;

Возврат Неопределено; // ничего не нашли

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

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

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

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

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

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

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

Для Каждого Колонка Из Строка.Колонки Цикл

Если Колонка.ЕстьОшибка Тогда

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

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

КонецЕсли;

КонецЦикла;

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

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

КонецЕсли;

КонецЦикла;

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

Сравнение вариантов

Флаговая переменная

Подходит для одного-двух уровней вложенности. Минус: лишняя переменная и дополнительные проверки усложняют код.

Вынос в функцию с «Возврат»

Лучший вариант при глубокой вложенности. Минус: нужно передавать параметры и продумывать возвращаемое значение.

Исключение через «ВызватьИсключение»

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

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

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

ИндексНайденного = -1;

Для Инд = 0 По Массив.ВГраница() Цикл

Если Массив[Инд] = ИскомоеЗначение Тогда

ИндексНайденного = Инд;

Прервать;

КонецЕсли;

КонецЦикла;

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

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

Порядок действий при выборе оператора
  1. 1
    Определите задачу: выйти из цикла совсем, пропустить итерацию или завершить всю процедуру.
  2. 2
    Для полного выхода из текущего цикла напишите «Прервать» внутри условия.
  3. 3
    Для пропуска элемента используйте «Продолжить» в начале итерации.
  4. 4
    Если после цикла нет обязательного кода — замените связку «Прервать» + проверку результата на «Возврат» из функции.
  5. 5
    Проверьте вложенность: убедитесь, что «Прервать» завершает именно тот цикл, который нужно.
  6. 6
    Запустите код в отладчике и пройдите по шагам, фиксируя, на какой итерации происходит выход.

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

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

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

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

Типичные ошибки
01
Ожидание, что «Прервать» остановит все вложенные циклы — на деле завершается только текущий, внешние продолжают работу.
02
«Продолжить» в цикле «Пока» до изменения переменной условия — бесконечный цикл и зависший сеанс.
03
«Возврат» внутри цикла перед обязательной финализацией — незакрытые транзакции и блокировки.
04
Код после безусловного «Прервать» в теле цикла — мёртвый код, который никогда не выполнится.
05
Прерывание поиска без признака «не найдено» — вызывающий код не может отличить пустой результат от ошибки.

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

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

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

Проверяйте три сценария: элемент найден в начале коллекции, элемент найден в конце, элемент не найден вовсе. Для последнего случая убедитесь, что вызывающий код корректно обрабатывает пустой результат (Неопределено, -1 или другой заданный признак).

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

Как проверить результат

Итерация выхода
Норма

Отладчик показывает выход на ожидаемой итерации

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

Цикл проходит все элементы, хотя нужный найден раньше

Значение результата после цикла
Норма

Переменная содержит найденный элемент или явный признак «не найдено»

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

Переменная не определена или содержит устаревшее значение

Вложенные циклы
Норма

Внешний цикл завершается через флаг или «Возврат»

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

Внешний цикл продолжает перебор после срабатывания «Прервать» во внутреннем

Цикл «Пока»
Норма

Условие рано или поздно становится ложным

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

Сеанс зависает, счётчик итераций растёт бесконечно

Итог

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

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

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

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

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

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

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

Можно ли прервать обход результата запроса?

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

Что будет, если использовать «Продолжить» вне цикла?

Конфигуратор выдаст синтаксическую ошибку при проверке модуля: операторы «Прервать» и «Продолжить» допустимы только внутри тела цикла. Модуль с такой ошибкой не будет скомпилирован и выполнен.

Как прервать цикл по нажатию пользователя?

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

Работает ли «Прервать» в управляемых формах и на мобильной платформе?

Да, операторы «Прервать», «Продолжить» и «Возврат» являются частью встроенного языка и работают одинаково во всех режимах исполнения: тонкий и толстый клиент, веб-клиент, сервер, мобильная платформа.