Почему пропадают данные из временного хранилища при подборе номенклатуры и как это исправить

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

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

Анализ механизма работы временного хранилища

Для начала проанализируем, как работает метод ПоместитьВоВременноеХранилище(). У него есть два ключевых параметра: объект, который мы сохраняем, и адрес (или уникальный идентификатор), к которому мы привязываем данные. Если мы опускаем второй параметр, платформа создает новый уникальный адрес, но при этом накладывает жесткие ограничения на «время жизни» этих данных.

Рассмотрим стандартную ошибку в коде формы подбора:


// В форме подбора
АдресВХранилище = ПоместитьВоВременноеХранилище(ОтобранныеЗапасы.Выгрузить());
// Данные помещены, адрес получен, но форма закрывается...

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

Решение проблемы: Привязка к уникальному идентификатору формы

Чтобы данные не терялись, мы должны явно указать платформе, как долго они должны храниться. Для этого используется второй параметр функции — УникальныйИдентификатор. Если передать туда идентификатор формы, данные будут жить до тех пор, пока эта форма открыта в сеансе пользователя.

Выясним важный нюанс: идентификатор какой именно формы нужно использовать? Если мы используем идентификатор самой формы подбора, то в момент ее закрытия (команда Закрыть()) данные могут быть удалены немедленно. Поэтому правильной практикой является привязка к форме-владельцу (форме документа, из которого вызван подбор).

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

  1. При открытии формы подбора передаем в нее уникальный идентификатор основной формы.
  2. В форме подбора при сохранении результата указываем этот идентификатор вторым параметром.

Пример кода в форме подбора:


// Владелец — это форма документа, которая открыла подбор
АдресВХранилище = ПоместитьВоВременноеХранилище(ОтобранныеЗапасы.Выгрузить(), ЭтаФорма.УникальныйИдентификатор);
// Если нужно передать конкретно во владелицу:
// АдресВХранилище = ПоместитьВоВременноеХранилище(ТЗ_Результат, ЭтаФорма.Владелец.УникальныйИдентификатор);

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

Почему таблица значений может оказаться пустой даже при верном адресе?

Проанализируем ситуации, когда адрес в хранилище жив, но данные внутри некорректны. Это может происходить из-за особенностей сериализации. Временное хранилище работает только с теми объектами, которые платформа может «упаковать» для передачи между сервером и клиентом. Сама ТаблицаЗначений прекрасно сериализуется, но если в её колонках содержатся типы, не поддерживающие сериализацию (например, COM-объекты или ссылки на объекты, которые уже удалены из памяти), вы можете получить пустой результат или ошибку при вызове ПолучитьИзВременногоХранилища().

Также стоит учитывать работу в кластере серверов. В старых версиях платформы (до 8.3.5) существовали проблемы с «перепрыгиванием» сеанса между рабочими процессами, из-за чего временное хранилище могло теряться. В современных версиях 1С эта проблема минимизирована, но всегда рекомендуется проверять актуальность версии платформы (не ниже 8.3.15+).

Альтернативные способы возврата данных из подбора

Многие разработчики считают использование временного хранилища для передачи небольших объемов данных излишним. Разберем более современные и надежные механизмы, которые предлагает платформа для управляемых форм.

1. Использование ОписанияОповещения (NotificationDescription)

Это стандарт де-факто для асинхронной работы в 1С. Мы не просто открываем форму, а передаем ей инструкции: «когда закроешься, вызови вот этот метод и передай туда результат».

В форме документа (вызов подбора):


Оповещение = Новый ОписаниеОповещения("ОбработатьПодбор", ЭтаФорма);
ПараметрыПодбора = Новый Структура;
ОткрытьФорму("Справочник.Номенклатура.Форма.ФормаПодбора", ПараметрыПодбора, ЭтаФорма, , , , Оповещение);

В форме подбора (завершение):


РезультатПодбора = ОтобранныеЗапасы.Выгрузить(); // Таблица значений
Закрыть(РезультатПодбора);

Этот способ избавляет нас от необходимости вручную управлять памятью в ПоместитьВоВременноеХранилище. Платформа сама передаст объект в процедуру ОбработатьПодбор.

2. Метод ОповеститьОВыборе

Если форма открыта в режиме выбора, можно использовать стандартный механизм. В форме подбора вызываем ОповеститьОВыборе(Значение), а в основной форме ловим результат в обработчике события ОбработкаВыбора.

Резюме и рекомендации

Подведем итог нашему исследованию. Чтобы избежать потери данных в хранилище, следуйте этим правилам:

  1. Всегда указывайте второй параметр в функции ПоместитьВоВременноеХранилище. Чаще всего это УникальныйИдентификатор текущей или вызывающей формы.
  2. Проверяйте тип данных. Убедитесь, что помещаемая ТаблицаЗначений не содержит специфических объектов, которые нельзя сериализовать.
  3. Используйте асинхронные вызовы. Для новых разработок старайтесь использовать ОписаниеОповещения и передачу данных напрямую через метод Закрыть(). Это более «чистый» код, который не засоряет серверную память временными объектами.
  4. Следите за контекстом. Помните, что данные во временном хранилище привязаны к сеансу. Если пользователь закроет браузер или сеанс завершится по таймауту, хранилище будет очищено вне зависимости от переданных идентификаторов.

Применяя эти подходы, вы обеспечите стабильную работу механизмов подбора и исключите жалобы пользователей на «пропадающие» товары из корзины подбора.

← На главную