Как реализовать автоматическое обновление списка документов у всех пользователей в 1С

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

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

Проблема локальных оповещений в рамках одного сеанса

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


&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
    // Это оповещение сработает ТОЛЬКО в текущем сеансе
    Оповестить("Запись_Реализация", ПараметрыЗаписи, Объект.Ссылка);
КонецПроцедуры

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

Решение 1: Встроенное автообновление динамического списка

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

У каждого динамического списка (который обычно отображается в форме списка документов) есть свойство Период автообновления. По умолчанию оно равно 0 (выключено).

  1. Откроем форму списка нужного документа в конфигураторе.
  2. Выберем основной реквизит формы с типом ДинамическийСписок (обычно он называется Список).
  3. В палитре свойств найдем раздел "Использование" и установим "Период автообновления" (в секундах).

Важный нюанс: Платформа рекомендует устанавливать значения не менее 60 секунд для снижения нагрузки на сервер. Однако на практике, если пользователей немного, а запрос списка оптимизирован, можно установить 20–30 секунд. Выясним причину, по которой не стоит ставить слишком маленькие значения (например, 1–3 секунды): каждое обновление — это полноценный запрос к базе данных, который при большом количестве пользователей может привести к существенным задержкам в работе SQL-сервера.

Решение 2: Использование Системы взаимодействия (Push-уведомления)

Проанализируем более современный подход, который появился в платформе 8.3. — Систему взаимодействия. Это отдельный компонент (сервер), который позволяет сеансам обмениваться сообщениями в реальном времени. Это наиболее "чистое" решение, так как оно работает по принципу Push: список обновится только тогда, когда действительно произошло изменение.

Разберем примерную схему реализации:

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


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

А в форме списка мы должны "подписаться" на это событие. В процедуре ПриОткрытии или ПриСозданииНаСервере настраивается обработчик:


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

Основное преимущество этого метода в том, что система не делает "холостых" запросов к базе данных каждые N секунд. Обновление происходит мгновенно после фиксации транзакции записи другим пользователем.

Решение 3: Реализация через служебный регистр ("Регистр уведомлений")

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

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

Рассмотрим пример кода для формы списка:


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

&НаКлиенте
Процедура ПроверитьОбновленияСписка()
    Если НужноОбновитьСписокНаСервере() Тогда
        Элементы.Список.Обновить();
    КонецЕсли;
КонецПроцедуры

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

Оптимизация производительности динамических списков

Независимо от выбранного способа обновления, важно убедиться, что сам динамический список работает максимально быстро. Проанализируем ключевые настройки:

Подведем итог: если вам нужно быстрое и простое решение для небольшой базы — используйте стандартный Период автообновления в свойствах списка (от 20 до 60 секунд). Если же система высоконагруженная и пользователей много, стоит рассмотреть Систему взаимодействия или механизм с регистром уведомлений, чтобы сберечь ресурсы сервера.

← На главную