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