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