Передача результатов выполнения тяжелых серверных вычислений из фонового задания в сеанс пользователя — одна из ключевых задач при оптимизации быстродействия 1С. Однако разработчики нередко сталкиваются с ситуацией, когда метод ПолучитьИзВременногоХранилища() возвращает Неопределено, либо механизм работает нестабильно и сбоит под нагрузкой. Разберем по шагам правила работы с временным хранилищем, типовые примеры кода, причины деградации сервиса сеансовых данных и надежные альтернативные решения.
В платформе 1С:Предприятие временное хранилище изолировано в рамках конкретного сеанса. Данные, сформированные в одном сеансе, недоступны для других сеансов. Исключением является обмен данными между фоновым заданием и сеансом, который инициировал его запуск.
Для корректной передачи данных необходимо соблюдать строгую последовательность действий:
УникальныйИдентификатор формы.Рассмотрим программный пример запуска фонового задания из формы и последующего считывания результата через обработчик ожидания.
В модуле формы подготавливаем адрес временного хранилища и запускаем фоновый процесс:
&НаСервере
Процедура ЗапуститьЗаданиеНаСервере()
// Инициализируем хранилище с привязкой к уникальному идентификатору формы
АдресВХранилище = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор);
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(АдресВХранилище);
// Запускаем фоновое задание в общем модуле
ФоновоеЗадание = ФоновыеЗадания.Выполнить("ДлительныеПроцессыСервер.ВыполнитьРасчет", ПараметрыЗадания);
ИдентификаторЗадания = ФоновоеЗадание.УникальныйИдентификатор;
КонецПроцедуры
В серверном общем модуле описываем процедуру фонового задания. Результат помещается по переданному адресу:
Процедура ВыполнитьРасчет(АдресВХранилище) Экспорт
РезультатТаблица = Новый ТаблицаЗначений;
РезультатТаблица.Колонки.Добавить("Код");
РезультатТаблица.Колонки.Добавить("Наименование");
Для Индекс = 1 По 1000 Цикл
НоваяСтрока = РезультатТаблица.Добавить();
НоваяСтрока.Код = Индекс;
НоваяСтрока.Наименование = "Элемент " + Индекс;
КонецЦикла;
// Помещаем результат по готовому адресу родительского сеанса
ПоместитьВоВременноеХранилище(РезультатТаблица, АдресВХранилище);
КонецПроцедуры
На клиенте периодически опрашиваем состояние задания. Считывание данных выполняем только после того, как статус фонового задания изменится на Завершено:
&НаКлиенте
Процедура ПроверитьРезультатФоновогоЗадания()
Результат = ПроверитьЗаданиеНаСервере(ИдентификаторЗадания, АдресВХранилище);
Если Результат <> Неопределено Тогда
ОтключитьОбработчикОжидания("ПроверитьРезультатФоновогоЗадания");
Сообщить("Данные успешно получены! Строк: " + Результат.Количество());
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверитьЗаданиеНаСервере(ИдентификаторЗадания, АдресВХранилище)
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
Если Задание <> Неопределено И Задание.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
Возврат ПолучитьИзВременногоХранилища(АдресВХранилище);
КонецЕсли;
Возврат Неопределено;
КонецФункции
Проанализируем технические причины, по которым временное хранилище перестает отдавать данные, особенно если сбой проявляется не сразу, а спустя несколько дней непрерывной работы базы:
ПоместитьВоВременноеХранилище(Неопределено) без второго параметра УникальныйИдентификатор, платформа связывает адрес с текущим вызовом сервера. При завершении вызова данные удаляются сборщиком мусора.Активно), родительский сеанс вернет Неопределено при вызове ПолучитьИзВременногоХранилища().rphost, при высокой нагрузке или утечках памяти в процессах кластера синхронизация между процессами может давать сбои.snccntx: Физически временные объекты кэшируются на диске сервера. Антивирусная проверка папки srvinfo или нехватка дискового пространства приводят к потере сеансовых данных.Если в многопользовательской базе наблюдается периодическая деградация сервиса временных хранилищ, применим следующие меры:
rphost (например, раз в сутки в нерабочее время) и добавим каталоги кластера (включая папку snccntx) в исключения антивируса.rphost сохраняем результат в системную таблицу базы через ХранилищеОбщихНастроек.Сохранить() по уникальному ключу фонового задания, а после чтения удаляем его методом ХранилищеОбщихНастроек.Удалить().ИдентификаторЗадания (тип УникальныйИдентификатор) и ресурсом Данные (тип ХранилищеЗначения). Этот способ обеспечивает максимальную надежность транзакционной записи и чтения больших объемов данных.ДлительныеОперации.ЗапуститьВыполнениеВФоне) позволяет автоматически обрабатывать отказоустойчивость, прогресс выполнения и очистку временных ресурсов.