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