В практике разработки на платформе «1С:Предприятие» (особенно в конфигурациях на обычных формах, таких как УТ 10.3) часто встречается ситуация, когда программисту необходимо получить от пользователя дополнительные данные непосредственно в момент проведения документа. Самым простым, но в корне неверным решением кажется вызов диалогового окна или формы выбора прямо в процедуре ПередЗаписью модуля объекта. В данной статье мы разберем, почему это приводит к остановке работы всей базы, и как правильно перестроить логику приложения, чтобы избежать конфликтов блокировок.
Разберем ситуацию, описанную автором темы. При попытке проведения документа открывается модальная форма. Пока пользователь раздумывает, какие параметры выбрать, другие пользователи не могут создать даже карточку товара или открыть константы. Почему так происходит?
Дело в том, что в 1С процедура ПередЗаписью модуля объекта всегда выполняется внутри транзакции базы данных. Транзакция — это неделимая последовательность операций. Как только она началась, система накладывает блокировки на таблицы, к которым обращается документ. В режиме автоматических блокировок (который чаще всего используется в старых конфигурациях) СУБД использует уровень изоляции SERIALIZABLE.
Рассмотрим цепочку событий:
ПередЗаписью.Если ожидание длится долго, происходит эскалация блокировок: вместо отдельных строк СУБД блокирует целые таблицы. Именно поэтому «стоит» вся база.
Важно четко понимать разницу между одноименными событиями в разных модулях. Проанализируем, где именно безопаснее всего взаимодействовать с пользователем.
В модуле формы событие ПередЗаписью срабатывает до начала транзакции базы данных. Это идеальное место для любых интерактивных действий: вопросов пользователю, открытия вспомогательных форм или выбора параметров оплаты.
В модуле объекта событие ПередЗаписью срабатывает после начала транзакции. Здесь интерактив строго запрещен. Более того, при программной записи документа (например, групповое перепроведение или обмен данными) форма просто не сможет открыться, что приведет к ошибке выполнения.
Это самый правильный и рекомендуемый путь. Мы должны собрать все необходимые данные до того, как система начнет блокировать таблицы БД. Рассмотрим пример кода для модуля формы:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Проверяем, что это именно проведение документа пользователем
Если РежимПроведения = РежимПроведенияДокумента.Проведение Тогда
// Если параметры оплаты еще не заполнены в реквизитах
Если НЕ ЗначениеЗаполнено(Объект.ВариантОплаты) Тогда
// Открываем форму выбора (не блокируя транзакцию!)
ВыбранныйВариант = ОткрытьФормуМодально("Справочник.ВариантыОплаты.ФормаВыбора");
Если ВыбранныйВариант = Неопределено Тогда
// Если пользователь передумал выбирать - отменяем запись
Отказ = Истина;
Возврат;
Иначе
// Записываем значение в реквизит объекта формы
Объект.ВариантОплаты = ВыбранныйВариант;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В этом случае транзакция начнется только после того, как процедура в форме отработает без ошибок, и все данные уже будут находиться в реквизитах документа.
Иногда логика требует, чтобы документ сначала был записан, а потом проведен с особыми параметрами. В этом случае можно использовать механизм «статусов» или вспомогательных реквизитов. Разберем этот алгоритм по шагам:
ПараметрыЗаполнены (тип Булево).ОбработкаПроведения добавьте проверку:
Если НЕ ПараметрыЗаполнены Тогда
Сообщить("Документ не может быть проведен без выбора параметров оплаты!");
Отказ = Истина;
Возврат;
КонецЕсли;
ПараметрыЗаполнены = Истина, и только затем вызывайте метод Записать(РежимЗаписиДокумента.Проведение).Проанализируем ситуацию, когда документы проводятся обработкой «Групповое проведение». В этом случае формы не открываются, и код в модуле формы не исполняется. Чтобы система не «упала», в модуле объекта необходимо предусмотреть значения по умолчанию или алгоритмы автоматического определения параметров.
Никогда не используйте функции типа Вопрос() или ОткрытьФорму() внутри модуля объекта без проверки на интерактивность. Однако лучшим стилем программирования считается полный отказ от таких конструкций в объектах, так как они делают код невозможным для работы в фоновых заданиях и внешних соединениях.
В обсуждении на форуме упоминался переход на управляемый режим блокировок. Выясним, поможет ли это. Переход на управляемые блокировки действительно снижает количество конфликтов, так как уровень изоляции меняется на Read Committed. В этом режиме чтение данных не блокирует их запись другими пользователями.
Однако, если вы оставите открытие формы внутри транзакции, вы все равно получите проблему, хотя и в меньшем масштабе. Исключительная блокировка на сам документ (табличную часть документа) все равно будет удерживаться до закрытия формы. Поэтому смена режима блокировок — это хорошая мера для общей производительности системы, но она не отменяет необходимости исправления архитектурных ошибок в коде.
Подводя итог нашему разбору, выделим основные правила работы с транзакциями и формами:
ОбработкеПроведения, но не пытайтесь их там «дозапросить» у пользователя.Соблюдение этих принципов позволит вам создавать стабильные и высокопроизводительные системы на базе 1С, в которых пользователи не будут мешать друг другу при выполнении повседневных операций.