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

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

Как прервать процедуру в 1С: все способы с примерами

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

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

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

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

Оператор Возврат — основной способ выйти из процедуры

Оператор Возврат немедленно прекращает выполнение текущей процедуры или функции и передаёт управление вызывающему коду. В функциях после Возврат указывается возвращаемое значение, в процедурах оператор пишется без значения.

Процедура ПровестиДокумент(ДокументСсылка)

Если ДокументСсылка.Пустая() Тогда

Сообщить("Документ не выбран");

Возврат; // выходим, дальнейший код не выполнится

КонецЕсли;

// основная логика проведения

// ...

КонецПроцедуры

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

В функции Возврат почти всегда возвращает результат:

Функция ПолучитьСкидку(Клиент)

Если Не ЗначениеЗаполнено(Клиент) Тогда

Возврат 0; // выходим с нулевой скидкой

КонецЕсли;

// расчёт скидки по условиям

Возврат РассчитатьСкидку(Клиент);

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

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

Прерывание циклов: Прервать и Продолжить

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

НайденнаяСтрока = Неопределено;

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

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

НайденнаяСтрока = Строка;

Прервать; // дальше перебирать не нужно

КонецЕсли;

КонецЦикла;

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

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

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

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

КонецЕсли;

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

КонецЦикла;

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

Выход из вложенных циклов

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

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

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

Если Строка.Цена < 0 Тогда

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

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

КонецЕсли;

КонецЦикла;

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

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

КонецЕсли;

КонецЦикла;

Типичные ошибки
01
Ожидание, что Прервать остановит сразу все вложенные циклы — он действует только на ближайший
02
Путаница между Прервать и Возврат: Возврат выходит из всей процедуры, а не только из цикла
03
Прерывание цикла по выборке запроса без проверки, что курсор выборки дочитан — при последующем обращении возможны неожиданные результаты

Исключения как способ прервать цепочку вызовов

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

Процедура ЗаписатьДанные(Параметры)

Если Параметры.Сумма < 0 Тогда

ВызватьИсключение "Сумма не может быть отрицательной";

КонецЕсли;

// запись данных

КонецПроцедуры

// вызывающий код

Попытка

ЗаписатьДанные(Параметры);

Исключение

Сообщить("Ошибка: " + ОписаниеОшибки());

КонецПопытки;

Если обработчика нет вообще, исключение дойдёт до платформы, и пользователь увидит системное окно ошибки, а выполнение всего обработчика (например, кнопки формы) будет остановлено. Это грубый, но рабочий способ гарантированно остановить выполнение.

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

Отмена транзакции — прерывание с откатом изменений

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

НачатьТранзакцию();

Попытка

ЗаписатьШапку(Данные);

ЗаписатьСтроки(Данные);

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

ВызватьИсключение "Обнаружены ошибки в данных";

КонецЕсли;

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

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

КонецПопытки;

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

Многие обработчики событий (например, ПередЗаписью, ОбработкаПроведения) уже выполняются внутри транзакции, которую открывает платформа. В них достаточно установить параметр Отказ = Истина — платформа сама отменит транзакцию и прервёт операцию.

Прерывание через параметр Отказ в обработчиках событий

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

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

Если Не ЗначениеЗаполнено(Ответственный) Тогда

Сообщить("Не заполнен ответственный");

Отказ = Истина;

Возврат;

КонецЕсли;

КонецПроцедуры

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

Для проведения документов есть дополнительный механизм: в обработчике ОбработкаПроведения можно формировать движения частично и при ошибке установить Отказ = Истина — платформа откатит всю транзакцию проведения целиком.

Как прервать выполнение при отладке

Во время отладки прервать выполняющийся код можно вручную из конфигуратора. Основные инструменты — точки останова и команда остановки.

Порядок действий при отладке
  1. 1
    Установите точку останова (F9) на нужной строке или включите «Остановка по ошибке» в меню Отладка
  2. 2
    Запустите отладку (F5) и выполните действие в клиентском приложении
  3. 3
    Когда выполнение остановится, используйте «Шагнуть через» (F10) или «Шагнуть в» (F11) для построчного анализа
  4. 4
    Чтобы полностью прервать выполнение процедуры, нажмите «Остановить» (Shift+F5) — сеанс отладки завершится
  5. 5
    Альтернатива: перетащите жёлтую стрелку текущей строки, чтобы пропустить часть кода без остановки сеанса

Полезная возможность — остановка по ошибке: в меню «Отладка → Остановка по ошибке» можно включить прерывание выполнения сразу в момент возникновения исключения, до того как оно будет обработано. Это позволяет увидеть точное место и состояние переменных в момент сбоя.

Для фоновых заданий и длительных операций на сервере отладка включается отдельно (настройка «Отладка по протоколу HTTP» или TCP), а принудительное прерывание выполняется через консоль кластера или административные функции сеанса.

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

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

Код после Возврат
Норма

Строки после оператора Возврат не выполняются (проверяется отладчиком)

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

Код выполняется — значит, Возврат стоит в другой ветке условия

Прерывание цикла
Норма

После Прервать выполняется первая строка за циклом, счётчик остаётся на найденном элементе

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

Цикл продолжает перебор — Прервать стоит во вложенной процедуре, а не в самом цикле

Откат транзакции
Норма

После ОтменитьТранзакцию() данные в базе не изменились

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

Часть записей сохранилась — транзакция была зафиксирована раньше или вложенные транзакции не сбалансированы

Выбор способа прерывания под задачу

Разные ситуации требуют разных механизмов. Неверный выбор приводит либо к «проглоченным» ошибкам, либо к избыточной сложности кода.

Маршрут решения

Как выбрать действие

Нужно выйти из процедуры при некорректных данныхИспользуйте Возврат с защитными проверками в начале процедуры
Нужно остановить перебор при нахождении элементаИспользуйте Прервать внутри цикла
Ошибка должна остановить несколько уровней вызововИспользуйте ВызватьИсключение и обработку через Попытка/Исключение
В базе уже внесены изменения, которые нужно откатитьИспользуйте транзакцию и ОтменитьТранзакцию()
Прерывается штатная операция записи или проведенияУстановите Отказ = Истина в обработчике события

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

Итог

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

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

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

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

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

Как прервать все вложенные циклы сразу?

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

Можно ли прервать проведение документа из ОбработкиПроведения?

Да. Установите параметр Отказ = Истина — платформа отменит транзакцию проведения, все сформированные движения будут откатаны, а документ останется непроведённым. Дополнительно можно вывести сообщение пользователю через Сообщить() или ВызватьИсключение с текстом причины.

Что произойдёт, если не обработать исключение?

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

Как остановить длительную обработку, запущенную пользователем?

Для интерактивных операций в цикле периодически вызывайте ОбработкаПрерыванияПользователя() — тогда нажатие Ctrl+Break прервёт выполнение. Для фоновых заданий используйте метод ПолучитьФоновоеЗадание и вызов Отменить(), а внутри самого задания периодически проверяйте необходимость завершения.

Почему Возврат в функции без значения — это ошибка?

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