Как исправить ошибку блокировки объекта после использования метода ОткрытьФорму() в 1С?

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

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

Анализ проблемы: почему возникает пессимистическая блокировка?

Разберем ситуацию, описанную в исходном вопросе. Программист использует стандартный метод ОткрытьФорму(), передавая в него ОписаниеОповещения. После выбора значения и закрытия формы выбора документ остается в памяти сервера или клиента как «редактируемый», хотя визуально окно может быть закрыто.

Выделим основные причины возникновения этой ошибки:

  1. Пессимистическая блокировка: Когда мы открываем форму существующего объекта (документа или элемента справочника), платформа автоматически устанавливает на него пессимистическую блокировку. Она должна сниматься в момент уничтожения объекта формы в памяти.
  2. Циклические ссылки: Использование ОписаниеОповещения, где вторым параметром передается ЭтаФорма, создает жесткую связь между подчиненной формой и родительской. Если эта связь не разрывается корректно, механизм Garbage Collector (сборщик мусора) не может удалить объекты из памяти.
  3. Неправильный владелец: Если при вызове формы выбора владельцем указывается вся форма документа (ЭтаФорма), а не конкретный элемент управления, жизненный цикл этих объектов становится избыточно связанным.

Метод 1. Использование механизма «Связи параметров выбора» (Рекомендуемый)

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

Рассмотрим по шагам, как это настроить:

  1. Откройте свойства реквизита в конфигураторе.
  2. Найдите пункт Связи параметров выбора.
  3. Добавьте новую связь: выберите поле Отбор.ИНН и укажите в качестве источника ваш реквизит ИНН (или ТекущиеДанные.ИНН, если это табличная часть).
  4. Установите режим выбора в Быстрый выбор или просто оставьте стандартную обработку.

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

Метод 2. Использование события ОбработкаВыбора и ОповеститьОВыборе

Если логика выбора слишком сложна для стандартных настроек, следует использовать механизм оповещения через владельца-элемента. Посмотрим на пример кода, который решает проблему зависания ссылок:

В модуле родительской формы (документа) вместо создания описания оповещения о закрытии, мы передаем в качестве владельца сам элемент формы:


&НаКлиенте
Процедура НСИКонтрагентыИННОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    
    // Останавливаем стандартное поведение
    СтандартнаяОбработка = Ложь;
    
    ПараметрыОтбора = Новый Структура("ИНН", ВыбранноеЗначение);
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", ПараметрыОтбора);
    
    // Ключевой момент: Владельцем назначаем Элемент (поле ввода), а не ЭтаФорма
    ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", ПараметрыФормы, Элемент);
    
КонецПроцедуры

Затем в этой же форме реализуем обработчик события ОбработкаВыбора для этого элемента или для всей формы:


&НаКлиенте
Процедура НСИКонтрагентыОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
    
    Если ЗначениеЗаполнено(ВыбранноеЗначение) Тогда
        ТекущиеДанные = Элементы.НСИКонтрагенты.ТекущиеДанные;
        ТекущиеДанные.ВидОперации = ПредопределенноеЗначение("Перечисление.ВидыОперацийИзмененияНСИ.ИзменениеРеквизитовОбъекта");
        ТекущиеДанные.СсылкаОснование = ВыбранноеЗначение;
    КонецЕсли;
    
КонецПроцедуры

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

Метод 3. Очистка ссылок в ОписанииОповещения

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

Выясним причину ошибки: часто блокировка возникает из-за того, что в ДополнительныеПараметры описания оповещения передаются ссылки на саму форму или её элементы. Постарайтесь передавать только примитивные типы (числа, строки) или ссылки на объекты базы данных (УИДы), но не контекст формы.

Опасность использования модальных окон

В некоторых обсуждениях предлагается использовать ОткрытьФормуМодально(). Важно понимать: это неправильный ответ. Использование модальности в современных версиях платформы 8.3 (особенно в интерфейсе «Такси») считается плохим тоном и часто технически ограничено настройками конфигурации («Режим использования модальности — Не использовать»).

Модальное окно останавливает выполнение кода на клиенте, что может визуально скрыть проблему блокировки, но не решает её на уровне управления памятью сервера. Более того, модальные окна не поддерживаются в веб-клиенте и мобильных приложениях 1С.

Резюме: правила «гигиены» при открытии форм

Чтобы избежать ошибок блокировки, придерживайтесь следующих правил:

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

Проанализировав все способы, мы видим, что наиболее стабильным решением является использование штатных событий ОбработкаВыбора, которые позволяют платформе 1С корректно управлять жизненным циклом объектов и своевременно освобождать блокировки в базе данных.

← На главную