При разработке конфигураций на платформе 1С:Предприятие часто возникает необходимость интерактивной или программной защиты документов и справочников от одновременного редактирования несколькими пользователями. Стандартный подход подразумевает использование метода Заблокировать(), обернутого в конструкцию Попытка ... Исключение. Однако в некоторых случаях при вызове этого метода происходят критические сбои платформы: сеанс аварийно завершается окном с «красным крестом», а перехват ошибки в секцию Исключение не срабатывает. Проанализируем, почему возникает эта проблема и какими способами можно восстановить штатную работу системы.
Рассмотрим стандартную конструкцию, которую разработчики часто применяют при открытии формы документа или перед началом выполнения программных обработок:
Если Не ЭтоНовый() Тогда
Попытка
ЭтотОбъект.Заблокировать();
Исключение
Предупреждение("Документ открыт или заблокирован другим пользователем!");
КонецПопытки;
КонецЕсли;
В нормальном режиме работы, если объект уже заблокирован другим сеансом, метод Заблокировать() вызывает исключительную ситуацию, которую перехватывает блок Исключение. Пользователю выводится предупреждение, после чего выполнение кода продолжается без завершения работы программы.
Однако при проявлении платформенного сбоя выполнение кода прерывается прямо на строчке ЭтотОбъект.Заблокировать(). Вместо перехода в секцию Исключение пользователь получает аварийное системное окно с предложением завершить работу программы. Диалоговое окно не дает возможности продолжать сеанс, а в журнале регистрации запись об ошибке может вовсе не фиксироваться.
Проанализируем ключевые причины, из-за которых конструкция Попытка ... Исключение пропускает ошибку блокировки:
DataEditLockService вызывает невосстановимое системное исключение. Платформа воспринимает сбой как фатальную ошибку ядра и мгновенно завершает клиентский процесс.Заблокировать() и Заблокирован().Заблокирован() проверяет состояние блокировки только текущего экземпляра объекта в памяти, а не состояние записи в базе данных другими сеансами. Это важно учитывать при проектировании логики проверки.Разберем по шагам, как исправить проблему падения платформы и восстановить корректную обработку блокировок.
Самым эффективным и гарантированным способом устранения данной ошибки является обновление платформы 1С. Поскольку невосстановимое исключение вызывается платформенной ошибкой сервиса блокировок, переход на более свежий релиз полностью решает проблему. На практике подтверждено, что обновление с версии 8.3.9 на релизы линейки 8.3.10 (например, 8.3.10.2699 и выше) устраняет фатальный сбой, и блок Попытка ... Исключение снова начинает штатно перехватывать ошибки блокировки объектов.
Если быстро обновить платформу не представляется возможным, рассмотрим альтернативный программный подход. Вместо вызова метода объекта Заблокировать() рекомендуется использовать метод глобального контекста ЗаблокироватьДанныеДляРедактирования(). Он работает с пессимистическими блокировками более предсказуемо и корректно связывает блокировку с ключом формы.
Посмотрим на пример применения в форме документа или информационной обработке:
Перем КлючБлокировки;
Попытка
// Устанавливаем блокировку через глобальный контекст
ЗаблокироватьДанныеДляРедактирования(СсылкаНаОбъект, КлючБлокировки, УникальныйИдентификатор);
Исключение
Сообщить("Не удалось заблокировать объект: " + ОписаниеОшибки());
КонецПопытки;
Для снятия такой блокировки используется парный метод РазблокироватьДанныеДляРедактирования():
РазблокироватьДанныеДляРедактирования(СсылкаНаОбъект, УникальныйИдентификатор);
Если ошибка проявилась внезапно после проведения динамического обновления, выполним комплекс профилактических и восстановительных работ:
%LocalAppData%\1C\1cv8 и %AppData%\1C\1cv8).rphosts, rmngr) для сброса зависших сеансовых блокировок.