Разработка и Конфигурация · 10 мин
Как с сервера вызвать процедуру на клиенте 1С
Разбираем, как с сервера вызвать процедуру на клиенте 1С: оповещения, обработчики ожидания, фоновые задания, длительные операции БСП. Примеры кода и типичные ошибки.
Напрямую вызвать клиентскую процедуру из серверного кода в 1С нельзя: серверный и клиентский контексты физически разделены, и у сервера нет ссылки на сеанс конкретного пользователя. Это ограничение архитектуры клиент-серверного режима, а не недоработка платформы. Однако задача «сообщить клиенту о событии на сервере» решается несколькими штатными механизмами.
Основные рабочие способы: оповещения пользователя через сообщения, система взаимодействия, фоновые задания с опросом состояния на клиенте, длительные операции БСП и метод Оповестить() в связке с клиентским обработчиком. Выбор зависит от того, что именно нужно: показать пользователю уведомление, обновить форму после серверной обработки или запустить на клиенте продолжение логики.
Ниже разобраны все варианты с примерами кода, условиями применения и типичными ошибками, из-за которых механизм «не работает» у начинающих разработчиков.
Почему прямой вызов невозможен и как обойти ограничение
В клиент-серверной архитектуре 1С код выполняется в разных процессах: серверный — на сервере приложений, клиентский — в процессе тонкого или толстого клиента. Серверный вызов инициируется клиентом, и пока вызов не завершён, сервер не может «достучаться» обратно. Директивы компиляции &НаСервере и &НаКлиенте как раз фиксируют, где живёт процедура.
Поэтому все рабочие схемы строятся по принципу «клиент спрашивает — сервер отвечает» или «сервер публикует событие — клиент его подхватывает». Попытка написать на сервере вызов клиентской процедуры приведёт либо к ошибке компиляции (процедура недоступна в серверном контексте), либо к ошибке исполнения.
Способ 1. Сообщение пользователю через СообщитьПользователю
Самый простой вариант, когда цель — не выполнить код на клиенте, а донести до пользователя информацию с сервера. Метод глобального контекста СообщитьПользователю() (или объект СообщениеПользователю) работает из серверного кода: сообщения накапливаются и показываются в клиентском сеансе после завершения серверного вызова.
Пример серверного кода:
&НаСервере
Процедура ОбработатьДанныеНаСервере()
// ... серверная обработка ...
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Обработано записей: " + Счетчик;
Сообщение.Сообщить();
КонецПроцедуры
Ограничение очевидно: это не вызов процедуры, а только текстовое уведомление. Подходит для статусов, предупреждений и ошибок, но не для запуска клиентской логики.
Способ 2. Фоновое задание с опросом результата на клиенте
Классическая схема для длительных серверных операций. Клиент запускает фоновое задание, получает его уникальный идентификатор и через ПодключитьОбработчикОжидания() периодически проверяет состояние. Когда задание завершено, клиент забирает результат из временного хранилища и вызывает нужную клиентскую процедуру.
&НаКлиенте
Процедура ЗапуститьОбработку(Команда)
Результат = ЗапуститьФоновоеЗаданиеНаСервере();
ИдентификаторЗадания = Результат.ИдентификаторЗадания;
АдресРезультата = Результат.АдресРезультата;
ПодключитьОбработчикОжидания("ПроверитьВыполнение", 2, Ложь);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьВыполнение()
Если ЗаданиеВыполнено(ИдентификаторЗадания) Тогда
ОтключитьОбработчикОжидания("ПроверитьВыполнение");
Данные = ПолучитьИзВременногоХранилища(АдресРезультата);
ОбработатьРезультатНаКлиенте(Данные); // нужная клиентская процедура
КонецЕсли;
КонецПроцедуры
На сервере результат помещается во временное хранилище через ПоместитьВоВременноеХранилище(Результат, АдресРезультата). Важно: адрес хранилища должен быть передан в фоновое задание как параметр, иначе клиент не сможет забрать данные.
- 1Создайте серверную процедуру длительной операции в общем модуле с флагом «Сервер»
- 2На клиенте запустите задание через ФоновыеЗадания.Выполнить и сохраните идентификатор и адрес хранилища
- 3Подключите обработчик ожидания с интервалом 1–3 секунды
- 4В обработчике проверяйте состояние задания серверным вызовом ЗаданиеВыполнено
- 5При завершении отключите обработчик, получите данные из хранилища и вызовите клиентскую процедуру обработки
Способ 3. Длительные операции БСП
Если конфигурация построена на Библиотеке стандартных подсистем, не нужно писать опрос вручную — используйте подсистему «Длительные операции». Она сама запускает фоновое задание, показывает форму ожидания и вызывает указанное клиентское оповещение по завершении.
&НаКлиенте
Процедура ВыполнитьДлительнуюОперацию(Команда)
ПараметрыВыполнения = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыВыполнения.ВыводитьОкноОжидания = Истина;
Оповещение = Новый ОписаниеОповещения("ПослеЗавершенияОперации", ЭтотОбъект);
ДлительнаяОперация = ВыполнитьОперациюНаСервере();
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, Оповещение, ПараметрыВыполнения);
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗавершенияОперации(Результат, ДопПараметры) Экспорт
Если Результат.Статус = "Выполнено" Тогда
Данные = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
// клиентская обработка результата
Иначе
ПоказатьПредупреждение(, Результат.КраткоеПредставлениеОшибки);
КонецЕсли;
КонецПроцедуры
Это рекомендуемый путь для типовых и доработанных конфигураций на БСП: меньше ручного кода, штатная обработка ошибок и прогресс выполнения.
Способ 4. Оповещения между формами и система взаимодействия
Метод Оповестить() работает в клиентском контексте и рассылает событие открытым формам, подписанным через ОбработкаОповещения. Сам по себе он не решает задачу «сервер → клиент», но входит в цепочку: серверный вызов завершается, клиент в обработчике результата вызывает Оповестить(), и другие формы реагируют.
Для сценария «сервер инициирует событие без запроса клиента» подойдёт система взаимодействия (если она развёрнута в информационной базе) или периодический опрос серверных данных обработчиком ожидания — например, проверка появления новых записей в регистре сведений «очереди уведомлений».
Ещё один практический приём — регистр сведений или очередь сообщений, куда серверные процедуры пишут события, а клиенты с интервалом читают новые записи. Это надёжно, но требует проектирования: очистка устаревших записей, блокировки при параллельной записи.
Сравнение способов
Только текстовое уведомление, никакой клиентской логики. Подходит для статусов и ошибок
Универсально, работает без БСП, но требует ручного управления обработчиком ожидания
Рекомендуемый вариант для конфигураций на БСП: штатное ожидание, ошибки и прогресс
Для событий, инициируемых сервером без действий пользователя; требует проектирования хранения и очистки
Типичные ошибки и ограничения
Самая частая ошибка — попытка вызвать из серверной процедуры клиентскую или обратиться к элементам формы в контексте &НаСервере без УправлениеФормой. Компилятор это отсекает, но в модулях без директив контекстной компиляции ошибка всплывает только в runtime.
Вторая группа проблем — работа с временным хранилищем: адрес теряется после закрытия формы, если не использован вариант хранения до конца сеанса; данные не сериализуются (нельзя передать, например, ссылку на COM-объект или несериализуемые типы). Третья — слишком частый опрос обработчиком ожидания: интервал меньше секунды грузит сервер лишними вызовами.
Как проверить, что механизм работает
После внедрения схемы проверьте полный цикл: серверная операция выполняется, клиент получает результат, целевая процедура вызывается с корректными данными. Полезно временно добавить вывод в журнал регистрации на сервере и Сообщить() в клиентском обработчике, чтобы увидеть порядок вызовов.
Как проверить результат
Состояние задания «Выполнено», данные читаются из хранилища
Задание в статусе «Ошибка» или хранилище пустое
Процедура оповещения срабатывает, точка останова в отладчике достигается
Обработчик не вызывается — проверьте Экспорт и имя процедуры
Опрос не чаще 1–2 секунд, вызовы короткие
Постоянные серверные вызовы, рост времени отклика сеансов
Отлаживать удобно через конфигуратор с включённой отладкой клиентского и серверного кода одновременно: в настройках отладки отметьте нужные типы соединений. Для фоновых заданий включайте отладку фоновых заданий отдельно — иначе точки останова в серверной процедуре задания не сработают.
FAQ
Можно ли с сервера показать модальное окно пользователю?
Нет, модальные и обычные диалоги доступны только в клиентском контексте. Правильная схема: серверный вызов возвращает признак необходимости диалога, а клиент в обработчике результата вызывает ПоказатьВопрос или ПоказатьПредупреждение.
Как серверу сообщить клиенту о событии, если пользователь ничего не нажимал?
Используйте обработчик ожидания на клиенте, который периодически опрашивает сервер (например, читает новые записи из регистра-очереди), либо систему взаимодействия, если она развёрнута в базе.
Почему обработчик оповещения длительной операции не вызывается?
Чаще всего процедура не экспортная, неверно указано имя в ОписаниеОповещения или форма-владелец уже закрыта. Проверьте слово Экспорт и совпадение имени процедуры с точностью до символа.
Можно ли передать с сервера на клиент таблицу значений?
Напрямую — нет, таблица значений не сериализуется для передачи. Преобразуйте её в массив структур или используйте ЗначениеВСтрокуВнутр/хранилище значения, либо поместите данные во временное хранилище в сериализуемом виде.
Что выбрать для обычной обработки данных по кнопке в форме?
Если конфигурация на БСП — длительные операции с ОжидатьЗавершение. Если БСП нет — фоновое задание с обработчиком ожидания и опросом состояния. Для быстрых операций достаточно обычного серверного вызова с возвратом результата.
Что важно запомнить
Прямого вызова клиентской процедуры с сервера не существует. Стройте обратную схему: сервер выполняет работу и сохраняет результат, клиент через фоновые задания, длительные операции БСП или обработчик ожидания получает данные и сам вызывает нужную процедуру. Следите за экспортностью обработчиков и временем жизни временного хранилища.