При разработке механизмов автоматизации в 1С программисты часто сталкиваются с необходимостью прервать выполнение кода при определенных условиях. Типичная ситуация: регламентное задание запускается по расписанию, проверяет настройки пользователя и, если текущее время не входит в разрешенный интервал, должно прекратить работу. Попытка использовать привычный метод ЗавершитьРаботуСистемы() в этом случае приводит к ошибке. Разберем подробно, почему так происходит и как правильно управлять жизненным циклом серверных процессов.
Проанализируем причину возникновения ошибки «Процедура или функция не определена (ЗавершитьРаботуСистемы)». Основная причина кроется в разделении контекстов исполнения кода в платформе 1С:Предприятие. Метод ЗавершитьРаботуСистемы() предназначен исключительно для работы в клиентском приложении (Тонкий клиент, Толстый клиент, Веб-клиент). Его задача — инициировать закрытие интерактивного окна программы, завершить текущий сеанс пользователя и освободить лицензию.
Регламентные и фоновые задания выполняются на стороне сервера в контексте рабочего процесса rphost. У этого процесса нет графического интерфейса, окон и «пользователя» в привычном понимании. Поэтому серверный контекст просто «не знает» о существовании команд управления оконным интерфейсом. Когда мы пытаемся вызвать клиентский метод на сервере, система выдает ошибку компиляции или времени выполнения.
Рассмотрим самый простой и правильный способ завершения работы регламентного задания. В отличие от интерактивного сеанса, фоновое задание не нужно «закрывать» специальной командой. Оно завершается автоматически, как только поток исполнения кода доходит до конца процедуры, являющейся точкой входа.
Если нам необходимо прервать выполнение алгоритма раньше (например, проверка условий в начале модуля), мы используем стандартный оператор Возврат. Проанализируем пример кода, который решает задачу автора темы:
Процедура ВыполнитьРегламентноеЗадание() Экспорт
// Получаем настройки из констант или регистра сведений
ВремяНачала = Константы.ВремяСтартаОбработки.Получить();
ТекущийЧас = Час(ТекущаяДата());
// Проверяем, наступило ли подходящее время
Если ТекущийЧас < ВремяНачала Тогда
// Просто выходим из процедуры.
// Система сама пометит задание как успешно выполненное.
Возврат;
КонецЕсли;
// Основная логика обработки документов
ПровестиДокументыНаСервере();
КонецПроцедуры
В данном примере, если условие не выполняется, оператор Возврат мгновенно прекращает работу процедуры. Менеджер заданий 1С фиксирует окончание выполнения и освобождает ресурсы сервера.
Иногда требуется не просто прекратить работу, а проинформировать администратора о том, что задание не смогло выполниться по какой-то критической причине. В этом случае вместо «тихого» выхода через Возврат следует использовать механизм исключений. Рассмотрим ситуацию, когда выполнение кода невозможно из-за отсутствия доступа к внешним ресурсам:
Если Не ПодключеноКВнешнейБазе Тогда
ВызватьИсключение "Ошибка: Не удалось установить соединение с внешней системой. Выполнение прервано.";
КонецЕсли;
При использовании ВызватьИсключение регламентное задание завершится аварийно. В консоли заданий и журнале регистрации оно получит статус «Завершено с ошибкой», что позволит быстро среагировать на проблему.
Проанализируем ситуацию, описанную автором: задание запускается каждый час, чтобы проверить, не пора ли начать работу. Это создает лишнюю нагрузку на сервер, особенно в высоконагруженных системах. Вместо «пустых прогонов» мы можем программно менять расписание самого регламентного задания. Рассмотрим, как это сделать с помощью объекта РегламентныеЗаданияМенеджер.
Если пользователь в интерфейсе меняет время запуска, мы можем выполнить следующий код (в контексте «Сервер» с административными правами):
МетаданныеЗадания = Метаданные.РегламентныеЗадания.МоеРегламентноеЗадание;
Задание = РегламентныеЗадания.НайтиПоМетаданным(МетаданныеЗадания)[0];
// Создаем новое расписание
НовоеРасписание = Новый РасписаниеРегламентногоЗадания;
НовоеРасписание.ДатаНачала = ТекущаяДата();
НовоеРасписание.ВремяНачала = НужноеВремяОтПользователя;
// Устанавливаем и записываем
Задание.Расписание = НовоеРасписание;
Задание.Записать();
Этот подход гораздо элегантнее: система запустит задание ровно в тот момент, когда это требуется, и нам не придется писать код для «досрочного завершения» внутри обработки.
Выделим ключевые моменты, которые помогут избежать ошибок при работе с фоновыми процессами:
ЗавершитьРаботуСистемы(), на сервере запрещены Предупреждение(), Вопрос(), ОткрытьФорму() и любые другие методы, ожидающие реакции пользователя.Предельное время выполнения. Если код «зациклится», сервер принудительно завершит поток по истечении этого времени.Объект = Неопределено) перед завершением процедуры, даже если вы используете Возврат.ЖурналРегистрации. Поскольку фоновое задание выполняется «невидимо», это единственный способ понять, почему оно завершилось раньше срока.Таким образом, мы выяснили, что для управления завершением серверного кода не требуются специальные команды «выхода из системы». Использование Возврат для штатных ситуаций и ВызватьИсключение для ошибок является стандартом разработки на платформе 1С:Предприятие 8.3.