При совместной работе множества пользователей в одной информационной базе 1С:Предприятия часто возникает классическая проблема конкурентного доступа. Два пользователя одновременно открывают один и тот же документ, начинают вносить изменения, но тот, кто пытается записать документ вторым, получает сообщение об ошибке, и все его введенные данные теряются. Это вызывает раздражение сотрудников и приводит к двойной работе.
В этой статье мы подробно разберем, как работает механизм блокировок в 1С, выясним причины возникновения конфликтов редактирования и научимся программно определять, что документ уже занят другим пользователем, прямо в момент открытия формы.
Давайте проанализируем, как платформа 1С по умолчанию обрабатывает совместный доступ к объектам. В системе функционируют два типа объектных блокировок:
Чтобы решить эту проблему кардинально, нам необходимо научиться принудительно устанавливать пессимистическую блокировку непосредственно при открытии формы документа. При необходимости можно воспользоваться материалом по принципам работы объектных блокировок.
Рассмотрим по шагам, как гарантировать, что второй пользователь не сможет даже начать редактирование документа, если он уже открыт у первого. Для этого нам потребуется наложить блокировку принудительно на сервере в момент инициализации формы.
Для управляемых форм правильным местом для вызова блокировки является обработчик события ПриЧтенииНаСервере или ПриСозданииНаСервере. Мы будем использовать метод глобального контекста ЗаблокироватьДанныеДляРедактирования.
Важное правило: Чтобы блокировка автоматически снялась при закрытии формы, необходимо передавать третьим параметром уникальный идентификатор формы (ЭтаФорма.УникальныйИдентификатор). В этом случае платформа сама свяжет время жизни блокировки с временем работы этой конкретной формы. Если сеанс пользователя аварийно завершится, платформа также автоматически очистит эту блокировку.
Давайте посмотрим на практический пример реализации этого механизма:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
// Проверяем, что документ уже записан в базу (для новых документов блокировка не нужна)
Если НЕ Объект.Ссылка.Пустая() Тогда
Попытка
// Пытаемся заблокировать объект на время работы формы
ЗаблокироватьДанныеДляРедактирования(Объект.Ссылка, , УникальныйИдентификатор);
Исключение
// Блокировка не удалась — значит, документ уже редактируется в другом сеансе
ЭтаФорма.ТолькоПросмотр = Истина;
// Получаем системное описание ошибки для вывода пользователю
ТекстОшибки = ОписаниеОшибки();
ПоказатьПредупреждениеПользователю(ТекстОшибки);
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Когда метод ЗаблокироватьДанныеДляРедактирования вызывает исключение, платформа возвращает в функцию ОписаниеОшибки() подробную системную информацию. Обычно эта строка выглядит следующим образом: «Объект уже заблокирован: компьютер: ИВАНОВ-ПК, пользователь: Иванов И.И., сеанс: 12345...».
Давайте разберем, как сделать это предупреждение более дружелюбным для конечного пользователя. Мы можем написать простую функцию парсинга системного сообщения, чтобы вычленить имя заблокировавшего сотрудника:
&НаСервере
Процедура ПоказатьПредупреждениеПользователю(ИсходныйТекстОшибки)
ИмяПользователя = "другим пользователем";
// Ищем вхождение ключевого слова "пользователь:"
ПозицияПользователя = Найти(ИсходныйТекстОшибки, "пользователь:");
Если ПозицияПользователя > 0 Тогда
ЧастьСтроки = Сред(ИсходныйТекстОшибки, ПозицияПользователя + СтрДлина("пользователь:"));
// Отсекаем оставшуюся часть после запятой, которая обычно разделяет параметры блокировки
ПозицияЗапятой = Найти(ЧастьСтроки, ",");
Если ПозицияЗапятой > 0 Тогда
ИмяПользователя = СокрЛП(Лев(ЧастьСтроки, ПозицияЗапятой - 1));
Иначе
ИмяПользователя = СокрЛП(ЧастьСтроки);
EndIf;
КонецЕсли;
// Выводим аккуратное сообщение пользователю
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
НСтр("ru = 'Внимание! Документ уже редактируется пользователем: " + ИмяПользователя + ". Форма открыта в режиме просмотра!'")
);
КонецПроцедуры
В процессе разработки вы можете столкнуться с двумя похожими методами платформы 1С. Важно понимать разницу между ними, чтобы не совершить архитектурных ошибок:
ЗаблокироватьДанныеДляРедактирования() — это универсальный метод глобального контекста. Он выполняется на сервере и позволяет блокировать любые ссылочные типы данных (документы, справочники), а также наборы записей регистров сведений. Это наиболее гибкий, современный и рекомендуемый метод для управляемых форм.ЗаблокироватьДанныеФормыДляРедактирования() — это метод объекта самой управляемой формы. Он блокирует только те данные, которые назначены основным реквизитом данной формы (например, реквизит Объект). Этот метод менее гибок, если вам требуется заблокировать связанные с документом подчиненные сущности или выполнить блокировку в отрыве от текущей формы.Иногда стандартный механизм пессимистических блокировок не решает всех задач бизнеса. Например, если руководству требуется видеть в режиме реального времени интерактивный список всех документов, которые в данный момент открыты сотрудниками компании. В этом случае разработчики создают кастомную подсистему мониторинга.
Для этого в конфигураторе создается непериодический независимый регистр сведений, например, АктивныеРедакторы со следующей структурой:
ОбъектРедактирования (тип: ЛюбаяСсылка)Пользователь (тип: СправочникСсылка.Пользователи)ДатаБлокировки (тип: Дата)При открытии формы документа выполняется запись в этот регистр сведений. Если запись уже существует, пользователю выдается предупреждение, а форма открывается в режиме просмотра. При закрытии формы запись из регистра удаляется.
Преимущества метода:
Недостатки метода:
ПолучитьСеансыИнформационнойБазы().Проанализируем нюансы работы блокировок при использовании Веб-клиента (через интернет-браузер). Метод ЗаблокироватьДанныеДляРедактирования прекрасно поддерживается в браузерах, однако здесь критически важно учитывать сетевую специфику.
Если пользователь просто закроет вкладку браузера с открытым документом, не нажав кнопку «Закрыть» в самой 1С, сервер не сразу узнает о закрытии формы. Сеанс пользователя перейдет в режим «спящего». Пессимистическая блокировка будет удерживаться на сервере до тех пор, пока не истечет время таймаута спящего сеанса (в стандартных настройках это около 20 минут), либо пока системный администратор не завершит данный сеанс вручную через консоль администрирования кластера 1С. Помните об этом нюансе при проектировании систем автоматизации для удаленных сотрудников.