Как программно запустить и контролировать фоновое задание в 1С 8.3?

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

В современной разработке на платформе 1С:Предприятие 8.3 одной из критически важных задач является обеспечение отзывчивости пользовательского интерфейса. Когда пользователю необходимо выполнить тяжелый расчет, сформировать сложный отчет или произвести синхронизацию с внешней системой, выполнение этих действий в основном потоке приводит к "зависанию" программы. Для решения этой проблемы мы используем механизм фоновых заданий. В данной статье мы подробно разберем, как правильно реализовать асинхронное выполнение кода на сервере, передать в него параметры и получить результат обратно.

Зачем нужны фоновые задания и как они работают?

Проанализируем базовый принцип: фоновое задание — это отдельный сеанс на сервере 1С, который выполняет назначенную ему процедуру независимо от сеанса пользователя. Это позволяет пользователю продолжать работу с другими формами и документами, пока сервер занят вычислениями. Основными объектами для работы являются менеджер ФоновыеЗадания и объект ФоновоеЗадание.

Рассмотрим основные этапы реализации этого механизма:

  1. Выделение кода для выполнения в отдельную процедуру в общем модуле.
  2. Программный запуск задания с передачей необходимых параметров.
  3. Организация мониторинга состояния задания на клиенте.
  4. Получение и обработка результата выполнения.

Шаг 1: Подготовка процедуры в общем модуле

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

Посмотрим на пример структуры такой процедуры. Предположим, нам нужно обработать большой массив данных и вернуть результат через временное хранилище:


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

Шаг 2: Программный запуск задания с сервера

Теперь разберем, как инициировать выполнение этой процедуры. Запуск осуществляется методом ФоновыеЗадания.Выполнить(). Нам необходимо передать имя процедуры, массив параметров, уникальный ключ (для предотвращения дублирования) и краткое описание.

Проанализируем код запуска на стороне сервера (например, в модуле управляемой формы):


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

Шаг 3: Мониторинг состояния на клиенте

После запуска задания нам нужно понять, когда оно завершится. Использовать бесконечный цикл на клиенте нельзя — это приведет к блокировке браузера или тонкого клиента. Вместо этого мы применим метод ПодключитьОбработчикОжидания.

Рассмотрим алгоритм действий на клиенте:


&НаКлиенте
Перем ИдентификаторФоновогоЗадания;
&НаКлиенте
Перем АдресХранилища;

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

&НаКлиенте
Процедура ПроверитьСтатусЗадания()
    
    Статус = ПроверитьЗавершениеНаСервере(ИдентификаторФоновогоЗадания);
    
    Если Статус = "Завершено" Тогда
        ОтключитьОбработчикОжидания("ПроверитьСтатусЗадания");
        ПолучитьИОбработатьРезультат();
    ИначеЕсли Статус = "Ошибка" Тогда
        ОтключитьОбработчикОжидания("ПроверитьСтатусЗадания");
        Предупреждение("Произошла ошибка при выполнении задания!");
    КонецЕсли;
    
КонецПроцедуры

Шаг 4: Проверка статуса и получение результата

Выясним, как проверить состояние задания на сервере. Для этого мы находим задание по его идентификатору и анализируем свойство Состояние.


&НаСервереБезКонтекста
Функция ПроверитьЗавершениеНаСервере(Идентификатор)
    
    Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
    
    Если Задание = Неопределено Тогда
        Возврат "Ошибка";
    КонецЕсли;
    
    Если Задание.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
        Возврат "Завершено";
    ИначеЕсли Задание.Состояние = СостояниеФоновогоЗадания.ЗавершеноАварийно Тогда
        Возврат "Ошибка";
    Иначе
        Возврат "Выполняется";
    КонецЕсли;
    
КонецФункции

&НаСервере
Процедура ПолучитьИОбработатьРезультат()
    
    // Извлекаем данные из временного хранилища
    Результат = ПолучитьИзВременногоХранилища(АдресХранилища);
    
    Если Результат <> Неопределено И Результат.Статус Тогда
        Объект.ИтоговоеЗначение = Результат.ИтоговаяСумма;
        Сообщить("Расчет окончен успешно!");
    КонецЕсли;
    
КонецПроцедуры

Важные нюансы и рекомендации

Рассмотрим несколько практических советов, которые помогут избежать типовых ошибок при работе с ФоновыеЗадания:

  1. Передача контекста: Помните, что фоновое задание не имеет доступа к данным текущей формы или открытым документам. Все необходимые данные (ссылки, структуры, таблицы) должны быть переданы через массив параметров.
  2. Временное хранилище: При использовании ПоместитьВоВременноеХранилище обязательно передавайте второй параметр — УникальныйИдентификатор формы. В противном случае данные будут удалены сразу после завершения серверного вызова, и фоновое задание не сможет записать результат, либо клиент не сможет его прочитать.
  3. Обработка исключений: Всегда оборачивайте код внутри фонового задания в блок Попытка...Исключение. Если в фоновом задании произойдет необработанная ошибка, оно завершится аварийно, и выяснить причину будет сложно без анализа журнала регистрации.
  4. Лимиты сервера: Не запускайте слишком много фоновых заданий одновременно. Каждое задание потребляет память и лицензию (в некоторых конфигурациях). В случае массовой обработки данных используйте механизмы очереди или разделяйте данные на крупные порции.

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

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

← На главную