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

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

1С: как прервать процедуру программно

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

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

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

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

Оператор Возврат — обычный выход из процедуры или функции

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

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

Процедура ПроверитьДанные(Данные)

Если Данные = Неопределено Тогда

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

КонецЕсли;

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

ОбработатьДанные(Данные);

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

Функция ПолучитьОстаток(Номенклатура)

Если Не ЗначениеЗаполнено(Номенклатура) Тогда

Возврат 0; // функция обязана вернуть значение

КонецЕсли;

Возврат ЗапроситьОстаток(Номенклатура);

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

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

ВызватьИсключение — прерывание с ошибкой и откатом транзакции

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

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

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

Если Товары.Количество() = 0 Тогда

ВызватьИсключение "Документ не содержит товаров. Проведение невозможно.";

КонецЕсли;

// движения по регистрам

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

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

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

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

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

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

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

Сообщить("Не заполнен контрагент. Запись отменена.");

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

Возврат;

КонецЕсли;

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

Сочетание Отказ = Истина и Возврат — правильный паттерн: отказ сообщает платформе об отмене действия, а возврат прекращает выполнение остального кода обработчика. Если поставить только Отказ = Истина без Возврат, код ниже продолжит выполняться и может, например, сформировать движения, которые всё равно не будут записаны.

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

Порядок действий при отмене записи документа
  1. 1
    В обработчике ПередЗаписью или ОбработкаПроведения проверьте необходимые условия
  2. 2
    При нарушении выведите понятное сообщение через Сообщить() или ВызватьИсключение
  3. 3
    Установите Отказ = Истина
  4. 4
    Добавьте Возврат, чтобы остальной код обработчика не выполнялся
  5. 5
    Проверьте результат: документ не записывается, сообщение видно пользователю

Прервать и Продолжить — управление циклами

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

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

Если Не ЗначениеЗаполнено(Строка.Номенклатура) Тогда

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

КонецЕсли;

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

Сообщить("Превышен лимит, обработка остановлена.");

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

КонецЕсли;

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

КонецЦикла;

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

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

Сравнение способов прерывания

Возврат

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

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

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

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

Отменяет штатное действие платформы (запись, проведение, закрытие формы) без аварийного завершения. Работает только в обработчиках с таким параметром.

Прервать / Продолжить

Управление только внутри циклов: остановка цикла или пропуск итерации. На код вне цикла не влияют.

Как прервать выполнение извне: фоновые задания и отладка

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

В конфигураторе при отладке выполнение останавливается точками останова, а кнопка «Остановить» (Shift+F5) полностью прекращает отлаживаемый сеанс. Учтите: принудительная остановка сеанса посреди транзакции оставляет транзакцию незавершённой до тайм-аута, что может временно блокировать записи в базе.

На управляемой форме для прерывания длительной операции стандартный подход — выполнять её в фоновом задании с выводом индикатора, а кнопку «Отмена» связывать с отменой задания. Не блокируйте интерфейс длительным циклом на клиенте: пользователь не сможет ничего нажать и воспримет это как зависание.

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

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

Обратная ошибка — попытка остановить проведение документа одним лишь Возврат. Код обработчика завершится, но платформа продолжит проведение, и документ запишется с некорректными данными. Для отмены обязательно нужен Отказ = Истина или исключение.

Третья группа ошибок связана с конструкцией Попытка...Исключение: пустой блок Исключение «проглатывает» все ошибки, включая непредвиденные, и диагностировать реальную проблему становится невозможно. Минимум — записывайте ОписаниеОшибки() в журнал регистрации.

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

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

После реализации прерывания проверьте поведение в трёх сценариях: штатная работа без прерывания, срабатывание условия прерывания и повторное выполнение после исправления данных. Убедитесь, что при отказе документ действительно не записан (проверьте базу, а не только сообщение), а при исключении транзакция откатилась и связанные данные не изменились.

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

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

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

Документ с некорректными данными
Норма

Не записывается, пользователь видит понятное сообщение

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

Записывается несмотря на проверку — значит, не установлен Отказ

Поведение при исключении
Норма

Транзакция откачена, связанные данные не изменились

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

Часть данных изменилась — исключение перехвачено и «проглочено» раньше времени

Журнал регистрации
Норма

Ошибка зафиксирована с описанием и местом возникновения

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

Ошибки нет — вероятно, пустой блок Исключение скрыл её

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

Итог

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

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

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

Чем отличается Возврат от ВызватьИсключение?

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

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

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

Можно ли прервать процедуру по таймеру?

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

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

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

Почему после Отказ = Истина код продолжает выполняться?

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

Как прервать процедуру на клиенте, не закрывая форму?

Операторы Возврат, Прервать и ВызватьИсключение работают на клиенте так же, как на сервере, и сами по себе форму не закрывают. Форма закрывается только если вы явно вызываете Закрыть() или необработанное исключение завершает сеанс — поэтому на клиенте исключения лучше перехватывать через Попытка...Исключение.