Как проверить, запущено ли фоновое задание в 1С и предотвратить дублирование процессов

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие часто возникает задача контроля за выполнением фоновых процессов. Типичный сценарий: регламентное задание автоматически получает почту каждые 10 минут, но пользователь также может нажать кнопку «Получить почту» вручную. Если эти процессы запустятся одновременно, данные могут задвоиться, а ресурсы сервера будут потрачены впустую. Рассмотрим подробнее, как корректно реализовать проверку активности фонового задания и какие инструменты платформы для этого предназначены. При обнаружении расхождений в учёте вследствие параллельного запуска процессов можно воспользоваться инструментом для автоматической сверки бухгалтерских и налоговых проводок между базами 1С.

Проблема «невидимого» активного состояния

Разберем ситуацию, с которой сталкиваются многие разработчики: при попытке получить список активных фоновых заданий через фильтр СостояниеФоновогоЗадания.Активно, система возвращает пустой массив, хотя задание явно выполняется. Или же, при просмотре всех заданий по наименованию, статус сразу меняется на «Задание выполнено», минуя промежуточные состояния.

Это может происходить по нескольким причинам:

  1. Транзакционность: Если проверка выполняется внутри транзакции, состояние задания может не обновиться в контексте текущего сеанса.
  2. Кеширование: Сведения о фоновых заданиях обновляются в кластере серверов с некоторой задержкой.
  3. Быстрое выполнение: Если процедура выполняется очень быстро, поймать момент «Активно» программно практически невозможно.

Метод 1. Простой перебор фоновых заданий

Проанализируем базовый способ проверки. Мы можем получить все фоновые задания по определенному признаку (например, по имени) и проверить их свойства в цикле. Это полезно, когда нам нужно понять, есть ли среди запущенных процессов хоть один активный.

Посмотрим на пример кода, который позволяет проверить наличие активных заданий:


Рез = Ложь;
НомерАктивногоЗадания = 0;
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Наименование", "Автополучение почты");

МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(ПараметрыОтбора);

Для каждого ТекЗадание Из МассивЗаданий Цикл
    Если ТекЗадание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
        НомерАктивногоЗадания = НомерАктивногоЗадания + 1;
        // Если мы нашли хотя бы одно активное задание, возвращаем Истина
        Если НомерАктивногоЗадания > 0 Тогда
            Рез = Истина;
            Прервать;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;
Возврат Рез;

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

Метод 2. Использование уникального ключа (Рекомендуемый)

Выясним наиболее надежный способ предотвращения повторных запусков, который предоставляет сама платформа. Метод ФоновыеЗадания.Выполнить() принимает параметр Ключ. Если запустить фоновое задание с определенным ключом, 1С автоматически не позволит запустить второе задание с таким же ключом, пока первое активно.

Рассмотрим архитектурный паттерн, который часто применяется в типовых конфигурациях. Мы создаем «обертку», которая проверяет состояние по ключу перед запуском основной логики.


Функция ПроцессУжеВыполняется() Экспорт
    УстановитьПривилегированныйРежим(Истина);
    
    // Ищем задания по уникальному ключу
    Фильтр = Новый Структура("Ключ", "УникальныйКлючЗагрузкиПочты");
    мОбмены = ФоновыеЗадания.ПолучитьФоновыеЗадания(Фильтр);
    
    Для каждого ФЗ Из мОбмены Цикл
        Если ФЗ.Состояние = СостояниеФоновогоЗадания.Активно Тогда
            Возврат Истина;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Ложь;
КонецФункции

Процедура ЗапуститьВыполнение() Экспорт
    Если НЕ ПроцессУжеВыполняется() Тогда
        // Запускаем фоновое задание, назначая ему тот самый Ключ
        ФоновыеЗадания.Выполнить("МойОбщийМодуль.РабочаяПроцедура", , "УникальныйКлючЗагрузкиПочты", "Загрузка почты (фоново)");
    Иначе
        Сообщить("Процесс уже запущен и выполняется в данный момент.");
    КонецЕсли;
КонецПроцедуры

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

Метод 3. Механизм управляемых блокировок

Если программная проверка списка заданий кажется вам недостаточно надежной (например, из-за специфики работы кластера), проанализируем метод управляемых блокировок. Этот способ гарантирует, что код не будет выполнен параллельно на уровне СУБД или менеджера блокировок 1С.

Мы можем установить блокировку на условный объект. Если другой сеанс (другое фоновое задание) попытается сделать то же самое, система выдаст ошибку или будет ждать освобождения, в зависимости от настроек.


Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.СостоянияОбменов"); // Можно использовать любой стабильный объект
ЭлементБлокировки.УстановитьЗначение("УзелОбмена", Константы.МойУзел.Получить());
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;

Попытка
    Блокировка.Заблокировать();
    // Здесь располагается основной код выполнения задачи
    ВыполнитьЗагрузкуДанных();
Исключение
    // Сюда попадем, если блокировка уже установлена другим заданием
    ЗаписатьЛог("Попытка параллельного запуска отклонена.");
КонецПопытки;

Метод 4. Использование БСП (Библиотека стандартных подсистем)

Если вы работаете в современной конфигурации (например, 1С:ERP, УТ 11 или БП 3.0), настоятельно рекомендуем использовать возможности общего модуля ДлительныеОперации. В БСП уже реализованы все необходимые проверки и механизмы ожидания. Быстро запустить такую логику в своей конфигурации поможет шаблон внешней обработки с фоновым выполнением на основе БСП.

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

Резюме и рекомендации

Подводя итоги, выделим основные правила работы с проверкой фоновых заданий, которые помогут корректно организовать процесс автоматического архивирования, обновления и тестирования баз 1С в «тихом» режиме.

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

← На главную