При разработке сложных систем автоматизации на платформе 1С:Предприятие 8 часто возникает необходимость запуска трудоемких процессов в фоновом режиме. Однако в процессе тестирования или при работе в условиях ограниченных ресурсов сервера может потребоваться жестко ограничить время выполнения таких операций. Например, если среднее время выполнения задания составляет несколько суток, а для целей отладки нам достаточно результатов работы программы за один час.
В этой статье мы подробно разберем, как реализовать механизм программной остановки фоновых заданий, используя штатные возможности платформы, и проанализируем технические нюансы, которые могут возникнуть при использовании метода Отменить().
Самый правильный и надежный способ управления временем выполнения группы фоновых заданий во внешней обработке — это использование метода ФоновыеЗадания.ОжидатьЗавершенияВыполнения(). Этот метод позволяет не просто «заморозить» выполнение основного потока до конца работы фоновых задач, но и задать конкретный интервал ожидания.
Рассмотрим алгоритм действий по шагам:
Проанализируем пример кода, реализующий эту логику:
// Создаем массив для хранения ссылок на запущенные задания
МассивЗаданий = Новый Массив;
// Запускаем несколько фоновых заданий
Для Итератор = 1 По 5 Цикл
ПараметрыПроцедуры = Новый Массив; // Ваши параметры
Задание = ФоновыеЗадания.Выполнить("МойОбщийМодуль.ВыполнитьДлительнуюОперацию", ПараметрыПроцедуры);
МассивЗаданий.Добавить(Задание);
КонецЦикла;
// Указываем время ожидания в секундах (например, 1 час = 3600 секунд)
ТаймАут = 3600;
Попытка
// Платформа будет ждать завершения всех заданий из массива в течение ТаймАут секунд
ФоновыеЗадания.ОжидатьЗавершенияВыполнения(МассивЗаданий, ТаймАут);
Сообщить("Все задания завершены успешно в отведенное время.");
Исключение
// Если время истекло или произошла ошибка в одном из заданий, мы попадем сюда
Сообщить("Время ожидания истекло или произошла ошибка. Начинаем принудительную остановку...");
Для Каждого ТекущееЗадание Из МассивЗаданий Цикл
// Проверяем, активно ли еще задание
Если ТекущееЗадание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
Попытка
// Посылаем сигнал об отмене
ТекущееЗадание.Отменить();
Сообщить("Задание " + ТекущееЗадание.УникальныйИдентификатор + " отменено.");
Исключение
Инфо = ИнформацияОбОшибке();
Сообщить("Не удалось отменить задание: " + ПодробноеПредставлениеОшибки(Инфо));
КонецПопытки;
КонецЕсли;
КонецЦикла;
КонецПопытки;
Важно понимать, что метод Отменить() не является аналогом системной команды «Kill Process». При вызове этого метода платформа лишь выставляет заданию специальный флаг — признак отмены. Само фоновое задание мгновенно не прекращается. Оно продолжает работу до тех пор, пока не встретит так называемую точку прерывания.
Разберем, что платформа 1С считает точками прерывания:
Запрос.Выполнить()).ПроверитьВывод() при работе с табличными документами.Если ваше фоновое задание выполняет сложный математический расчет внутри цикла без обращения к базе данных, оно может проигнорировать команду Отменить() на долгое время. Выясним причину такого поведения: сервер 1С не прерывает выполнение кода «на полуслове», чтобы не нарушить целостность структур данных в памяти процесса rphost. Он ждет безопасного момента, когда управление передается системным механизмам доступа к данным.
Если использование штатного метода Отменить() не приносит результата (например, задание «зависло» в бесконечном цикле без запросов к БД), можно прибегнуть к программному управлению сеансами через интерфейс администрирования кластера (COM или rac/ras).
Каждое фоновое задание неразрывно связано с конкретным сеансом. Мы можем найти сеанс, у которого свойство ФоновоеЗаданиеИдентификатор совпадает с ID нашего задания, и принудительно разорвать это соединение. Это жесткий способ, который гарантированно завершит выполнение кода на сервере.
Посмотрим на алгоритм такого решения (схематично):
V83.COMConnector.TerminateSession() для этого сеанса.Внимание: Данный метод требует административных прав и наличия настроенного сервера администрирования. Его следует использовать только в крайних случаях, так как некорректное завершение сеанса может привести к временным блокировкам в базе данных.
Проанализируем ситуацию с сохранностью данных при отмене фонового задания. В 1С действует правило: если фоновое задание прерывается (штатно или принудительно), все незавершенные транзакции, открытые внутри этого задания, будут откачены.
Если ваша обработка создает объекты внутри задания, рассмотрите два варианта архитектуры:
Отменить() и прохождения ближайшей точки прерывания.Таким образом, для достижения целей тестирования, описанных автором темы, метод с ОжидатьЗавершенияВыполнения(Массив, ТаймАут) является оптимальным. Он позволяет внешней обработке контролировать жизненный цикл запущенных потоков, не вмешиваясь в код общих модулей конфигурации.