К статье
Практический материал

Разработка и Конфигурация · 12 мин

Массив как глобальная переменная в 1С: способы реализации

Как в 1С реализовать массив как глобальную переменную: общие модули, переменные модуля приложения, параметры сеанса и хранилище значений. Примеры кода и ошибки.

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

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

Ниже разобраны рабочие подходы с примерами кода, их ограничения, типичные ошибки и критерии выбора. Материал ориентирован на разработчиков конфигураций на управляемых формах, но часть приёмов применима и в обычном приложении.

Почему в 1С нет настоящих глобальных массивов

Глобальные переменные в 1С существуют только внутри конкретного модуля: переменная, объявленная в разделе переменных модуля, видна во всех процедурах этого модуля, но не за его пределами. Чтобы сделать её доступной извне, объявляют с ключевым словом Экспорт — однако это работает только для модулей, к которым можно обратиться по имени: общих модулей и модуля приложения.

Дополнительное ограничение — разделение контекстов. Общий модуль с признаком «Сервер» исполняется на сервере, с признаком «Клиент» — на клиенте. Массив, созданный на сервере, физически недоступен клиентскому коду без передачи через вызов сервера. Кроме того, массив нельзя напрямую поместить в параметр сеанса: туда допускаются только простые типы и сериализуемые объекты, поэтому массив упаковывают в ХранилищеЗначения.

Ещё одна тонкость касается времени жизни. Переменная общего модуля на клиенте живёт в рамках сеанса клиентского приложения; на сервере — в рамках серверного вызова или сеанса в зависимости от настроек повторного использования возвращаемых значений модуля. Это частая причина ошибок: разработчик ожидает, что данные «помнятся», а модуль пересоздаётся.

Способ 1: общий модуль с экспортной переменной

Самый простой вариант — создать общий модуль (например, ГлобальныеДанныеКлиент с признаком «Клиент (управляемое приложение)») и объявить в нём переменную с экспортом:

// Общий модуль ГлобальныеДанныеКлиент, клиентский

Перем ГлобальныйМассив Экспорт;

// Инициализация при первом обращении

ГлобальныйМассив = Новый Массив;

Обращение из любого клиентского кода выглядит так: ГлобальныеДанныеКлиент.ГлобальныйМассив.Добавить(НовоеЗначение). Массив будет единым для всего клиентского сеанса — изменения в одной форме видны в другой.

Более надёжная практика — не экспортировать переменную напрямую, а сделать её приватной и предоставить экспортные функции доступа. Это защищает от случайной замены массива другим объектом и позволяет контролировать инициализацию:

Перем ГлобальныйМассив;

Функция ПолучитьМассив() Экспорт

Если ГлобальныйМассив = Неопределено Тогда

ГлобальныйМассив = Новый Массив;

КонецЕсли;

Возврат ГлобальныйМассив;

КонецФункции

Способ 2: переменная модуля управляемого приложения

Модуль управляемого приложения исполняется на клиенте и доступен из любой клиентской формы. Переменная, объявленная в нём с Экспорт, фактически становится глобальной для клиентского сеанса:

// Модуль управляемого приложения

Перем КэшДанных Экспорт;

Процедура ПриНачалеРаботыСистемы()

КэшДанных = Новый Массив;

КонецПроцедуры

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

Ограничение очевидно: данные живут только на клиенте и теряются при перезапуске приложения. Кроме того, модуль приложения нельзя вызвать с сервера, поэтому для серверной логики этот способ не подходит.

Способ 3: параметр сеанса с хранилищем значения

Если массив нужен на сервере и должен быть привязан к сеансу пользователя, используют параметр сеанса типа ХранилищеЗначения. Массив упаковывается при записи и распаковывается при чтении:

// Запись

ПараметрыСеанса.МойМассив = Новый ХранилищеЗначения(МассивДанных);

// Чтение

МассивДанных = ПараметрыСеанса.МойМассив.Получить();

Если МассивДанных = Неопределено Тогда

МассивДанных = Новый Массив;

КонецЕсли;

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

Минус — накладные расходы на сериализацию при каждом обращении и необходимость вручную перезаписывать параметр после изменения массива: распакованная копия не связана с хранилищем. Также объёмные массивы увеличивают потребление памяти на каждый сеанс, что при большом числе пользователей может стать проблемой.

Способ 4: временное хранилище и адрес как глобальный идентификатор

Для передачи массива между клиентом и сервером в рамках сеанса применяют временное хранилище. Массив помещается туда на сервере, а глобально доступным «ключом» становится адрес (строка), который можно хранить в переменной модуля приложения или передавать между формами:

// Серверный вызов

АдресВХранилище = ПоместитьВоВременноеХранилище(МассивДанных, УникальныйИдентификаторФормы);

// Позже — извлечение

МассивДанных = ПолучитьИзВременногоХранилища(АдресВХранилище);

Это стандартный механизм для длительных операций и обмена данными между формами. Время жизни данных привязано либо к форме (если передан её уникальный идентификатор), либо к сеансу. Способ хорошо масштабируется по объёму, но требует аккуратного управления адресами: потерянный адрес означает недоступные данные до очистки хранилища.

Сравнение способов и критерии выбора

Каждый подход имеет свою область применения. Сводная таблица помогает быстро определить подходящий вариант:

СпособКонтекстВремя жизниОграничения
Общий модуль с экспортной переменнойКлиент или серверСеанс / до пересоздания модуляРиск сброса при повторном использовании значений
Модуль управляемого приложенияТолько клиентСеанс клиентаНедоступен с сервера
Параметр сеанса + ХранилищеЗначенияСерверСеанс пользователяСериализация при каждом обращении, память на сеанс
Временное хранилищеСервер, обмен с клиентомСеанс или жизнь формыНужно управлять адресами вручную
Маршрут решения

Как выбрать действие

Массив нужен только в клиентском коде одного сеансаИспользуйте общий клиентский модуль или модуль приложения с ленивой инициализацией
Массив нужен в серверных процедурах в рамках сеанса пользователяПримените параметр сеанса с хранилищем значения или временное хранилище
Массив передаётся между формами или является результатом длительной операцииПоместите его во временное хранилище и передавайте адрес
Данные должны переживать перезапуск сеансаСохраняйте их в базу: константа с хранилищем значения или регистр сведений

Типичные ошибки и как их избежать

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

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

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

Типичные ошибки
01
Экспорт переменной без функции-получателя — массив обнуляется при пересоздании модуля, ошибка проявляется не сразу
02
Изменение копии массива из параметра сеанса без обратной записи — изменения теряются без сообщений
03
Хранение больших массивов в параметрах сеанса — рост потребления памяти пропорционально числу пользователей
04
Обращение к клиентской глобальной переменной из серверного кода — ошибка компиляции или пустые данные
05
Использование глобального массива для данных, которые должны переживать перезапуск — данные теряются, нужна база

Проверка результата и отладка

После внедрения глобального массива проверьте три вещи: инициализацию при первом обращении, видимость изменений из разных точек кода и поведение при граничных ситуациях (переоткрытие формы, новый серверный вызов, перезапуск клиента).

Контрольные точки

Как проверить результат

Первое обращение к массиву
Норма

Массив создан и пуст, ошибок нет

Тревожный признак

Неопределено или ошибка обращения к переменной

Добавление элемента в одной форме, чтение в другой
Норма

Элемент виден в обеих формах

Тревожный признак

Во второй форме массив пуст — контексты разделены или модуль пересоздан

Повторное обращение после серверного вызова
Норма

Данные сохранились

Тревожный признак

Массив обнулился — проверьте повторное использование значений модуля

Изменение массива из параметра сеанса
Норма

После записи обратно данные читаются с изменениями

Тревожный признак

Изменения пропадают — забыта обратная запись в параметр

Для отладки удобно использовать отладчик с точкой останова на функции-получателе: видно, сколько раз вызывается инициализация. Если инициализация срабатывает чаще одного раза за сеанс на клиенте — значит, модуль пересоздаётся, и стоит пересмотреть его настройки. В серверном коде полезно логировать количество элементов массива при записи и чтении, чтобы отловить потерю данных.

Итог

Что важно запомнить

Глобальный массив в 1С реализуется через общий модуль или модуль приложения (клиент), параметр сеанса с хранилищем значения (сервер) или временное хранилище (обмен между формами). Всегда используйте функцию-получатель с ленивой инициализацией и помните: данные из параметров сеанса и временного хранилища — это копии, изменения нужно записывать обратно.

Частые вопросы

Можно ли объявить массив прямо в конфигурации, чтобы он был виден везде?

Нет, в метаданных конфигурации нет объекта «глобальная переменная». Ближайшие аналоги — экспортная переменная общего модуля или модуля приложения, либо параметр сеанса. Для постоянного хранения между сеансами используются константы и регистры сведений.

Почему массив в общем модуле иногда обнуляется?

Чаще всего причина — включённое свойство модуля «Повторное использование возвращаемых значений», при котором платформа пересоздаёт модуль и сбрасывает его переменные. Также клиентский модуль пересоздаётся при перезапуске клиентского приложения. Надёжное решение — инициализация массива внутри функции-получателя при каждом обращении.

Как передать глобальный массив с клиента на сервер?

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

Что выбрать для данных, общих для всех пользователей, а не одного сеанса?

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

Есть ли альтернатива массиву для глобального кэша с поиском по ключу?

Да, для кэша удобнее соответствие: поиск по ключу выполняется напрямую без перебора. Приём хранения тот же — переменная общего модуля с функцией-получателем. Если кэш большой и общий для всех пользователей, рассмотрите фоновое обновление и хранение в базе.

Влияет ли глобальный массив на производительность?

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