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