Как исправить ошибку при установке константы в фоновом процессе 1С и почему регистр сведений лучше

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

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

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

Выясняем причину: иллюзия ошибки отладчика

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

Константы.СК_СтатусОграниченияДоступности.Установить(Истина);

или при использовании менеджера значения константы:


ПолучСтатус = Константы.СК_СтатусОграниченияДоступности.CreateValueManager();
ПолучСтатус.Прочитать();
ПолучСтатус.Значение = Истина;
ПолучСтатус.Записать();

отладчик на шаге записи выдает ошибку: «Обращение к процедуре объекта как к функции (Установить)» или «(Записать)». Почему это происходит?

Дело в особенностях работы механизма вычисления выражений в конфигураторе 1С (окно «Табло» или сочетание клавиш Shift + F9):

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

Важный вывод: На самом деле код успешно выполняется при обычном пошаговом прохождении (по клавише F10). Ошибка возникает исключительно из-за попытки принудительного «вычисления» процедуры внутри самого отладчика. Если запустить процесс без точек останова, константа будет успешно записана в базу данных.

Проблема кэширования констант в сеансах

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

Рассмотрим, как это устроено на уровне платформы:

Транзакционные блокировки при записи констант

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

В реляционных базах данных (MS SQL Server, PostgreSQL) все константы конфигурации чаще всего хранятся в одной физической таблице СУБД. При записи любой константы платформа 1С накладывает транзакционную блокировку на всю таблицу констант.

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

Правильное архитектурное решение: Регистр сведений

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

Создадим новый регистр сведений со следующими параметрами:

Давайте напишем код для установки флага блокировки из фонового процесса:


&НаСервере
Процедура УстановитьБлокировкуРМК(ЗначениеБлокировки) Экспорт
    
    МенеджерЗаписи = РегистрыСведений.СК_СтатусДоступностиРМК.СоздатьМенеджерЗаписи();
    // Если у регистра есть измерения (например, Магазин или Касса), заполняем их здесь
    // МенеджерЗаписи.Магазин = ПараметрыОбмена.Магазин;
    
    МенеджерЗаписи.БлокировкаАктивна = ЗначениеБлокировки;
    МенеджерЗаписи.Записать(Истина); // Записываем с замещением существующей записи
    
КонецПроцедуры

Почему использование независимого регистра сведений является единственно верным решением для данной задачи?

  1. Построчные блокировки СУБД: При записи в регистр сведений блокируется только одна конкретная строка (по набору измерений), а не вся таблица. Другие пользователи и фоновые процессы продолжают беспрепятственно работать со своими записями.
  2. Отсутствие агрессивного кэширования: При обращении к регистру сведений (через запрос или метод получения среза последних) платформа всегда обращается напрямую к базе данных. Это гарантирует, что сеанс пользователя мгновенно получит актуальный статус блокировки, установленный фоновым заданием.
  3. Гибкость и масштабируемость: Использование регистра позволяет легко доработать систему. Если в будущем потребуется блокировать РМК не во всей базе сразу, а выборочно (для конкретного магазина, кассового узла или конкретного пользователя), нам достаточно будет просто добавить соответствующее измерение в регистр сведений. С константой сделать это было бы невозможно.

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

← На главную