Передача данных между фоновым заданием и основным сеансом пользователя — одна из классических задач при разработке на платформе 1С:Предприятие 8. Часто разработчики сталкиваются с ситуацией, когда данные, помещенные во временное хранилище внутри фонового задания, оказываются недоступными в родительском сеансе. Разберем подробно, почему это происходит и как правильно организовать обмен данными.
Основная проблема заключается в понимании жизненного цикла временного хранилища. Сеанс фонового задания и сеанс пользователя — это разные области памяти. Чтобы «пробросить» данные между ними, платформа использует специальный механизм идентификации. Рассмотрим алгоритм действий, который гарантирует успех.
Шаг 1. Подготовка в родительском сеансе. Перед запуском задания необходимо создать «ячейку» в хранилище родительского сеанса и получить её адрес. Важно привязать этот адрес к уникальному идентификатору формы, чтобы данные не очистились преждевременно.
&НаСервере
Функция ЗапуститьВыполнениеНаСервере()
// Создаем пустую запись в хранилище, привязанную к форме
АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено, ЭтаФорма.УникальныйИдентификатор);
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(ПараметрыЗадачи);
МассивПараметров.Добавить(АдресХранилища); // Передаем адрес как параметр
РезультатЗадания = ФоновыеЗадания.Выполнить("МойОбщийМодуль.ВыполнитьДлительнуюОперацию", МассивПараметров);
Возврат АдресХранилища;
КонецФункции
Шаг 2. Выполнение в фоновом задании. В процедуре фонового задания мы используем переданный адрес. Проанализируем важный нюанс: функция ПоместитьВоВременноеХранилище должна принимать адрес вторым параметром.
Процедура ВыполнитьДлительнуюОперацию(ПараметрыЗадачи, АдресХранилища) Экспорт
Результат = Новый Структура;
Результат.Вставить("Статус", "Успешно");
Результат.Вставить("Данные", ПолучитьНужныеДанные(ПараметрыЗадачи));
// Помещаем результат по старому адресу
ПоместитьВоВременноеХранилище(Результат, АдресХранилища);
КонецПроцедуры
Важное замечание: данные не появятся в родительском сеансе мгновенно. Платформа синхронизирует содержимое хранилища только после успешного завершения фонового задания. Если вы попытаетесь прочитать данные через обработчик ожидания, пока задание еще имеет состояние Активно, вы получите Неопределено или пустую строку.
Выясним, как правильно дождаться результата. Обычно для этого используется обработчик ожидания на клиенте. Разберем пример кода для отслеживания завершения.
&НаКлиенте
Процедура ПроверитьСтатусЗадания()
Если ЗаданиеЗавершено(ИдентификаторЗадания) Тогда
ОтключитьОбработчикОжидания("ПроверитьСтатусЗадания");
ПолучитьРезультатИзХранилища();
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ЗаданиеЗавершено(Ид)
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Ид);
Возврат (Задание.Состояние = СостояниеФоновогоЗадания.Завершено);
КонецФункции
Когда состояние задания станет Завершено, выполнение функции ПолучитьИзВременногоХранилища(АдресХранилища) вернет структуру, которую мы подготовили внутри задания.
Если задача длится долго, пользователю важно видеть прогресс. Поскольку временное хранилище «отдает» данные только в конце, проанализируем альтернативный метод — использование механизма сообщений пользователю (ПолучитьСообщенияПользователю).
Внутри фонового задания мы можем отправлять сообщения, которые родительский сеанс может перехватывать «на лету»:
// В фоновом задании
Процедура ВыполнитьЭтап(НомерЭтапа)
ТекстСообщения = "Выполняется этап: " + НомерЭтапа;
Сообщить(ТекстСообщения);
КонецПроцедуры
В родительском сеансе в обработчике ожидания мы считываем эти сообщения:
&НаСервере
Функция ПолучитьПрогрессЗадания(ИдентификаторЗадания)
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
МассивСообщений = Задание.ПолучитьСообщенияПользователю(Истина); // Истина - очистить очередь
Если МассивСообщений.Количество() > 0 Тогда
ПоследнееСообщение = МассивСообщений[МассивСообщений.Количество() - 1].Текст;
Возврат ПоследнееСообщение;
КонецЕсли;
Возврат "";
КонецФункции
Для передачи сложных структур через сообщения (например, текущий процент и текст статуса) рекомендуется сериализовать данные в строку JSON.
Рассмотрим еще один полезный метод — свойство Информация объекта ФоновоеЗадание. Это строковое поле (длиной до 1024 символов), которое можно обновлять в процессе работы. Оно отлично подходит для простых статусов.
ФоновыеЗадания.ТекущееФоновоеЗадание().Информация = "Обработано 50%";Проанализируем ситуации, в которых код может не работать:
ПоместитьВоВременноеХранилище была успешно выполнена до возникновения ошибки.Итог: Для надежной передачи результата используйте связку «заранее созданный адрес в хранилище + ожидание завершения задания». Для оперативного информирования пользователя лучше подходят сообщения или свойство Информация.