Как правильно заблокировать объект от редактирования другими пользователями в 1С?

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

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

Проблема использования связки Заблокировать и Разблокировать

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


Попытка
    Объект.Заблокировать();
    Объект.Разблокировать();
Исключение
    Предупреждение("Документ уже редактируется другим пользователем");
КонецПопытки;

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

Особенности блокировок в Управляемых формах (УФ)

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

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

Пессимистическая блокировка через ЗаблокироватьДанныеДляРедактирования

Для того чтобы заблокировать данные на всё время работы пользователя с формой, 1С предоставляет специальный механизм — пессимистическую блокировку. В управляемых формах для этого используется метод ЗаблокироватьДанныеДляРедактирования(). Этот метод привязывает блокировку не к переменной в коде, а к идентификатору формы или сеанса.

Рассмотрим пример реализации такой блокировки в процедуре открытия формы или при выборе объекта в обработке:


// В процедуре открытия или выбора объекта
Попытка
    ЗаблокироватьДанныеДляРедактирования(СсылкаНаОбъект, , УникальныйИдентификатор);
Исключение
    Сообщить("Объект уже заблокирован: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

В данном примере УникальныйИдентификатор — это идентификатор формы. Платформа будет «держать» объект заблокированным до тех пор, пока эта форма не будет закрыта. Это единственный надежный способ в управляемом приложении гарантировать, что второй пользователь не начнет редактирование того же объекта через интерфейс.

Механизмы в Обычных формах

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

Посмотрим на пример использования метода Заблокирован(). Следует помнить, что метод Объект.Заблокирован() возвращает состояние блокировки именно для текущего экземпляра в текущем сеансе. Он не всегда корректно показывает, заблокирован ли объект кем-то другим в базе. Для проверки «чужой» блокировки всегда надежнее использовать Попытка ... Исключение с реальным вызовом Заблокировать().


// В обычной форме документа
Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    Попытка
        ЭтотОбъект.Заблокировать();
    Исключение
        ТекстОшибки = ИнформацияОбОшибке().Описание;
        Сообщить("Не удалось открыть для редактирования: " + ТекстОшибки);
        Отказ = Истина;
    КонецПопытки;
КонецПроцедуры

Оптимистическая блокировка — штатный механизм платформы

Не стоит забывать, что в 1С по умолчанию работает оптимистическая блокировка. Она основана на версии объекта. При чтении данных в форму система запоминает версию документа. В момент записи платформа проверяет, не изменилась ли версия в базе данных. Если кто-то другой успел записать документ, пока у первого пользователя была открыта форма, система выдаст ошибку: «Объект изменен или удален».

Этот механизм работает автоматически и не требует программного кода, но он срабатывает только в момент записи. Если бизнес-процесс требует, чтобы пользователь узнавал о занятости объекта в момент открытия, необходимо реализовывать пессимистическую блокировку, описанную выше.

Итоги и рекомендации

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

  1. Не используйте связку Заблокировать() и Разблокировать() в одном блоке кода, если ваша цель — удержать объект от редактирования. Это лишь кратковременная проверка, которая мгновенно освобождает ресурс.
  2. В управляемых формах применяйте метод ЗаблокироватьДанныеДляРедактирования(). Это глобальный метод платформы, который связывает блокировку с сеансом или формой.
  3. Помните, что любая программная блокировка в 1С снимается автоматически при завершении сеанса пользователя или при закрытии формы (если был передан её идентификатор).
  4. Если вы работаете с объектом в коде (например, в фоновом задании или обработке), всегда используйте конструкцию Попытка ... Исключение вокруг метода Заблокировать(), чтобы корректно обработать ситуацию, когда объект уже занят другим процессом.

Рассмотрим еще один важный момент: блокировка Заблокировать() не запрещает чтение объекта. Другие пользователи смогут открыть документ для просмотра или прочитать его данные программно через Ссылка.ПолучитьОбъект(), но они не смогут установить на него свою блокировку или записать изменения до тех пор, пока вы не освободите объект.

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

← На главную