В практике разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда данные, помещенные во временное хранилище, бесследно исчезают. Типичный сценарий: из документа открывается форма подбора, пользователь выбирает товары, код отрабатывает помещение таблицы значений в хранилище, но при попытке получить эти данные в основной форме оказывается, что адрес ведет в «пустоту» или возвращает Неопределено. Разберем детально, почему это происходит и как правильно управлять жизненным циклом временного хранилища.
Для начала проанализируем, как работает метод ПоместитьВоВременноеХранилище(). У него есть два ключевых параметра: объект, который мы сохраняем, и адрес (или уникальный идентификатор), к которому мы привязываем данные. Если мы опускаем второй параметр, платформа создает новый уникальный адрес, но при этом накладывает жесткие ограничения на «время жизни» этих данных.
Рассмотрим стандартную ошибку в коде формы подбора:
// В форме подбора
АдресВХранилище = ПоместитьВоВременноеХранилище(ОтобранныеЗапасы.Выгрузить());
// Данные помещены, адрес получен, но форма закрывается...
В данном случае данные будут существовать в хранилище ровно до тех пор, пока не завершится текущий серверный вызов или не наступит следующий вызов сервера из этого же сеанса. Как только управление возвращается на клиента, а затем происходит любое другое обращение к серверу (например, при закрытии формы или обновлении интерфейса), сборщик мусора платформы имеет полное право очистить память.
Чтобы данные не терялись, мы должны явно указать платформе, как долго они должны храниться. Для этого используется второй параметр функции — УникальныйИдентификатор. Если передать туда идентификатор формы, данные будут жить до тех пор, пока эта форма открыта в сеансе пользователя.
Выясним важный нюанс: идентификатор какой именно формы нужно использовать? Если мы используем идентификатор самой формы подбора, то в момент ее закрытия (команда Закрыть()) данные могут быть удалены немедленно. Поэтому правильной практикой является привязка к форме-владельцу (форме документа, из которого вызван подбор).
Рассмотрим правильный алгоритм реализации:
Пример кода в форме подбора:
// Владелец — это форма документа, которая открыла подбор
АдресВХранилище = ПоместитьВоВременноеХранилище(ОтобранныеЗапасы.Выгрузить(), ЭтаФорма.УникальныйИдентификатор);
// Если нужно передать конкретно во владелицу:
// АдресВХранилище = ПоместитьВоВременноеХранилище(ТЗ_Результат, ЭтаФорма.Владелец.УникальныйИдентификатор);
Важный момент: если вы используете фиксированную строку в качестве адреса, каждое новое выполнение метода ПоместитьВоВременноеХранилище по этому адресу будет затирать предыдущие данные. Это удобно для экономии памяти, если подбор производится многократно в рамках одного сеанса работы с документом.
Проанализируем ситуации, когда адрес в хранилище жив, но данные внутри некорректны. Это может происходить из-за особенностей сериализации. Временное хранилище работает только с теми объектами, которые платформа может «упаковать» для передачи между сервером и клиентом. Сама ТаблицаЗначений прекрасно сериализуется, но если в её колонках содержатся типы, не поддерживающие сериализацию (например, COM-объекты или ссылки на объекты, которые уже удалены из памяти), вы можете получить пустой результат или ошибку при вызове ПолучитьИзВременногоХранилища().
Также стоит учитывать работу в кластере серверов. В старых версиях платформы (до 8.3.5) существовали проблемы с «перепрыгиванием» сеанса между рабочими процессами, из-за чего временное хранилище могло теряться. В современных версиях 1С эта проблема минимизирована, но всегда рекомендуется проверять актуальность версии платформы (не ниже 8.3.15+).
Многие разработчики считают использование временного хранилища для передачи небольших объемов данных излишним. Разберем более современные и надежные механизмы, которые предлагает платформа для управляемых форм.
1. Использование ОписанияОповещения (NotificationDescription)
Это стандарт де-факто для асинхронной работы в 1С. Мы не просто открываем форму, а передаем ей инструкции: «когда закроешься, вызови вот этот метод и передай туда результат».
В форме документа (вызов подбора):
Оповещение = Новый ОписаниеОповещения("ОбработатьПодбор", ЭтаФорма);
ПараметрыПодбора = Новый Структура;
ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбора", ПараметрыПодбора, ЭтаФорма, , , , Оповещение);
В форме подбора (завершение):
РезультатПодбора = ОтобранныеЗапасы.Выгрузить(); // Таблица значений
Закрыть(РезультатПодбора);
Этот способ избавляет нас от необходимости вручную управлять памятью в ПоместитьВоВременноеХранилище. Платформа сама передаст объект в процедуру ОбработатьПодбор.
2. Метод ОповеститьОВыборе
Если форма открыта в режиме выбора, можно использовать стандартный механизм. В форме подбора вызываем ОповеститьОВыборе(Значение), а в основной форме ловим результат в обработчике события ОбработкаВыбора.
Подведем итог нашему исследованию. Чтобы избежать потери данных в хранилище, следуйте этим правилам:
ПоместитьВоВременноеХранилище. Чаще всего это УникальныйИдентификатор текущей или вызывающей формы.ТаблицаЗначений не содержит специфических объектов, которые нельзя сериализовать.ОписаниеОповещения и передачу данных напрямую через метод Закрыть(). Это более «чистый» код, который не засоряет серверную память временными объектами.Применяя эти подходы, вы обеспечите стабильную работу механизмов подбора и исключите жалобы пользователей на «пропадающие» товары из корзины подбора.