Что вызывается раньше: ПриОткрытии() формы рабочего стола или ПриНачалеРаботыСистемы() в 1С?

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

При разработке мобильных рабочих мест (например, для терминалов сбора данных на базе Android) или создании кастомных десктопных интерфейсов для операторов склада и кассиров разработчики часто сталкиваются с неожиданным поведением платформы «1С:Предприятие 8». Нам кажется логичным, что сначала система должна полностью загрузиться, выполнить глобальные процедуры инициализации в модуле управляемого приложения, а уже затем открыть интерфейсное окно — форму начальной страницы (рабочего стола). Однако на практике мы сталкиваемся с тем, что оборудование (сканеры штрихкодов, ТСД, фискальные регистраторы), подключаемое в форме, отказывается работать при старте.

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

В чем суть проблемы?

Рассмотрим стандартную ситуацию. Разработчик создает конфигурацию (или дорабатывает существующую, например, на мобильной платформе) для терминала сбора данных (ТСД). На начальный рабочий стол выводится общая форма (назовем ее Форма1), где пользователь должен сразу же начать сканирование штрихкодов. Логика разработчика выглядит следующим образом:

  1. В модуле управляемого приложения в процедуре ПриНачалеРаботыСистемы() прописывается код инициализации торгового оборудования (БПО) или глобальных параметров сеанса.
  2. В модуле самой Формы1 в обработчике события ПриОткрытии() вызывается функция подключения конкретного сканера к этой форме.

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

Давайте разберемся, почему так происходит, и проанализируем внутренний порядок загрузки платформы.

Архитектурная логика запуска системы «1С:Предприятие»

Описанное поведение не является ошибкой или багом мобильной платформы. Это строго задокументированный базовый алгоритм инициализации интерфейса в «1С:Предприятии 8» (как в десктопной версии, так и в мобильном клиенте/платформе). Посмотрим на пошаговую схему запуска клиентского приложения:

  1. Вызов события УстановкаПараметровСеанса. Выполняется в модуле сеанса на стороне сервера. Это самый первый этап, на котором подготавливаются ключевые параметры сеанса текущего пользователя.
  2. Вызов обработчика ПередНачаломРаботыСистемы. Данное событие выполняется на клиенте в модуле управляемого приложения. На этом шаге интерфейс пользователя еще физически не создан. Здесь категорически нельзя открывать интерактивные формы (за исключением простейших диалогов предупреждения). В этой процедуре можно проверить условия запуска и, при необходимости, отказаться от старта системы, передав в параметр Отказ значение Истина.
  3. Инициализация главного окна и форм начальной страницы. На этом этапе платформа начинает строить пользовательский интерфейс. Она считывает настройки рабочего стола конфигурации и создает формы, которые должны быть отображены на начальной странице. Соответственно, последовательно срабатывают их внутренние обработчики событий:
    • ПриСозданииНаСервере() формы рабочего стола;
    • ПриОткрытии() формы рабочего стола.
  4. Вызов обработчика ПриНачалеРаботыСистемы. Это событие модуля управляемого приложения вызывается строго после того, как главное окно и формы начальной страницы уже созданы, открыты и выведены на экран. Отказаться от запуска системы на данном этапе уже невозможно.
  5. Вызов переопределяемых событий БСП. Если ваша конфигурация разработана на базе Библиотеки стандартных подсистем (БСП), далее срабатывают процедуры вроде ПослеНачалаРаботыСистемы().

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

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

Как решить проблему подключения оборудования?

Для обхода этой архитектурной особенности существует несколько проверенных временем решений. Рассмотрим их подробно и выберем наиболее эффективные практики.

Решение 1: Использование однократного обработчика ожидания (рекомендуемый способ)

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

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


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

&НаКлиенте
Процедура ПодключитьОборудованиеПослеСтарта() Экспорт
    // Этот код гарантированно выполнится ПОСЛЕ завершения работы процедуры ПриНачалеРаботыСистемы()
    Попытка
        ИнициализироватьОборудованиеФормы();
    Исключение
        ЗаписатьЛогОшибки(ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

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

Решение 2: Перенос инициализации оборудования в ПередНачаломРаботыСистемы

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

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


// В модуле управляемого приложения
Процедура ПередНачаломРаботыСистемы(Отказ)
    // Инициализируем только неинтерактивные структуры данных и загружаем компоненты
    ИнициализироватьДрайверыОборудования();
КонецПроцедуры

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

Решение 3: Ленивая (отложенная) инициализация

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

Не подключайте сканер штрихкодов или терминал непосредственно при открытии рабочего стола. Вместо этого выполняйте подключение:

Посмотрим на пример реализации ленивой инициализации при нажатии кнопки начала работы:


&НаКлиенте
Процедура НачатьРаботуВыполнить(Кнопка)
    // Оборудование подключается только тогда, когда пользователь явно изъявил желание работать
    Если Не ОборудованиеПодключено Тогда
        ПодключитьРабочееОборудование();
    КонецЕсли;
    
    ПерейтиКРежимуСканирования();
КонецПроцедуры

Этот подход не только решает проблему с порядком загрузки, но и экономит ресурсы мобильного устройства (батарею ТСД, оперативную память), так как внешние компоненты не будут висеть в памяти, если пользователь просто зашел посмотреть отчет или справочник на рабочем столе.

Решение 4: Использование событий БСП

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

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

Резюме

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

Для решения этой проблемы используйте простой и надежный механизм отложенного вызова через ПодключитьОбработчикОжидания() с минимальным интервалом времени. Это позволит вам сохранить логику инициализации оборудования в модуле управляемого приложения и гарантирует корректную работу ТСД и сканеров как на мобильных платформах, так и на настольных ПК.

← На главную