Как подключить обработчик ожидания в 1С 8.3
Содержание
Обработчик ожидания подключают методом ПодключитьОбработчикОжидания("ИмяПроцедуры", Интервал) прямо в модуле формы. Процедура-обработчик — клиентская, без параметров, с директивой &НаКлиенте; интервал задаётся в секундах. Этого достаточно, чтобы 1С сама вызывала вашу процедуру через заданные промежутки времени — для автообновления списка, опроса фонового задания или отложенного действия после открытия формы.
Дальше — синтаксис метода, куда его ставить, как через него следить за серверным заданием и как не оставить в базе «вечный» таймер, который дёргает сервер каждую секунду. Код — под платформу 8.3 с управляемыми формами (интерфейс «Такси»).
Что это за механизм и где он срабатывает
Обработчик ожидания — это клиентский таймер. Платформа запоминает имя вашей процедуры и интервал, а затем вызывает процедуру в промежутках, когда клиент простаивает: между действиями пользователя, пока никакой другой код не выполняется.
Ключевой момент: обработчик работает только в клиентском контексте — на толстом и тонком клиенте, в веб-клиенте. На сервере его нет. Если вам нужна параллельная работа именно на сервере, это другой инструмент — фоновые и регламентные задания (о связке с ними ниже).
Из этого следуют два практических вывода:
- 🧵 Код обработчика выполняется в основном потоке клиента. Тяжёлая операция внутри него подвесит интерфейс — пользователь не сможет кликать, пока процедура не отработает.
- ⏱ Интервал — это минимальная задержка, а не точное время. Если клиент занят (открыто блокирующее окно, выполняется длинный серверный вызов), вызов откладывается.
Технически платформа ставит вызов вашей процедуры в очередь и исполняет её, как только освобождается основной поток клиента. Поэтому таймер не прерывает выполняющийся код — он дожидается паузы.
Типовые задачи, под которые механизм подходит:
- 🔄 периодически обновлять данные на форме (список заявок, остатки, статусы);
- 📡 опрашивать состояние фонового задания и показать результат по завершении;
- ⏳ выполнить отложенное действие один раз после открытия формы (подсказку, автофокус);
- 💾 автосохранять черновик или настройки с заданной частотой.
Для лёгких повторяющихся действий обработчик ожидания — правильный выбор. Для расчётов и импорта выносите работу на сервер, а таймер используйте только как «пульс» для опроса.
Синтаксис метода и его параметры
Полная форма вызова:
ПодключитьОбработчикОжидания(<ИмяПроцедуры>, <Интервал>, <Однократно>)
Параметры:
- ИмяПроцедуры (обязательный, тип Строка) — имя процедуры, которую надо вызывать. Передаётся строкой, без скобок и параметров. Строка должна точно совпадать с именем процедуры в модуле.
- Интервал (обязательный, тип Число) — промежуток в секундах. Значение больше нуля; максимум — 2 073 600 секунд (это ровно 24 суток). Если нужен интервал меньше секунды, он должен быть кратен
0,1(то есть минимум 0,1 секунды). - Однократно (необязательный, тип Булево, по умолчанию
Ложь) — еслиИстина, процедура вызывается один раз, после чего обработчик снимается сам.
Вызванная процедура обязана быть без параметров и доступна на клиенте.
В управляемом приложении используют метод формы ПодключитьОбработчикОжидания. Внутри модуля формы его вызывают просто по имени — без ЭтотОбъект. Одноимённый метод глобального контекста считается устаревшим, новый код на него опирать не стоит.
Повторный вызов ПодключитьОбработчикОжидания с тем же именем процедуры не создаёт второй таймер, а переустанавливает интервал для уже подключённого. А вот процедуры с разными именами работают параллельно — можно держать несколько обработчиков сразу.
Подключаем обработчик на клиенте
Минимальный рабочий пример — автообновление данных на форме раз в 5 секунд. Подключаем обработчик при открытии формы:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПодключитьОбработчикОжидания("ОбновитьДанныеНаФорме", 5);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьДанныеНаФорме()
ОбновитьДанныеНаСервере();
КонецПроцедуры
&НаСервере
Процедура ОбновитьДанныеНаСервере()
// перечитываем данные, пересчитываем реквизиты формы
КонецПроцедуры
Разберём по шагам, что здесь происходит:
ПриОткрытии— клиентское событие формы. Как только форма открылась, регистрируем таймер.- Имя
"ОбновитьДанныеНаФорме"в строке точно совпадает с именем клиентской процедуры ниже. - Сама процедура-обработчик только запускает работу, а тяжёлую часть делегирует серверному методу.
Если действие нужно выполнить один раз с задержкой — например, показать подсказку через 2 секунды после открытия, — добавляем третий параметр:
ПодключитьОбработчикОжидания("ПоказатьПодсказку", 2, Истина);
С флагом Истина обработчик сработает один раз и отключится сам — отдельный ОтключитьОбработчикОжидания не нужен.
Опрос фонового задания через обработчик
Самый частый сценарий — долгая операция на сервере (импорт, выгрузка, пересчёт), а на клиенте надо показать результат, когда она закончится. Обработчик ожидания здесь играет роль «пульса»: он периодически спрашивает у сервера, завершилось ли задание.
Схема такая: клиент запускает фоновое задание на сервере, сохраняет его идентификатор, подключает обработчик и начинает опрос.
&НаСервере
Процедура ЗапуститьЗаданиеНаСервере()
Задание = ФоновыеЗадания.Выполнить(
"Обработки.ИмпортДанных.МодульОбъекта.ВыполнитьИмпорт", , , "Импорт данных");
ИдентификаторЗадания = Строка(Задание.УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ЗапуститьИмпорт(Команда)
ЗапуститьЗаданиеНаСервере();
ПодключитьОбработчикОжидания("ПроверитьСостояниеЗадания", 1);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьСостояниеЗадания()
Если ЗаданиеЗавершено(ИдентификаторЗадания) Тогда
ОтключитьОбработчикОжидания("ПроверитьСостояниеЗадания");
ОбработатьРезультатЗадания();
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ЗаданиеЗавершено(Ид)
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(
Новый УникальныйИдентификатор(Ид));
Возврат Задание = Неопределено
ИЛИ Задание.Состояние <> СостояниеФоновогоЗадания.Активно;
КонецФункции
Что важно в этом коде:
- Идентификатор задания хранится в реквизите формы (
ИдентификаторЗадания) как строка — объектФоновоеЗаданиена клиент не передаётся, с ним работают только на сервере. - Как только состояние задания перестаёт быть
Активно, опрос прекращаем вызовомОтключитьОбработчикОжидания. Иначе таймер продолжит слать серверные вызовы вхолостую. - Состояние может быть не только
Завершено, но иЗавершеноАварийноилиОтмененоАдминистратором— поэтому проверяем «не активно», а дальше разбираемся с результатом.
Если в вашей конфигурации есть Библиотека стандартных подсистем (БСП), не пишите опрос руками. Модуль ДлительныеОперации на сервере и ДлительныеОперацииКлиент на клиенте делают ровно это — запускают задание и опрашивают его обработчиком ожидания с адаптивным интервалом. Ручная схема нужна там, где БСП нет.
В клиент-серверной базе фоновые задания выполняются рабочими процессами кластера. В файловой базе они тоже работают, но запускаются в отдельном сеансе, и для их выполнения клиент, как правило, должен оставаться открытым — это стоит учитывать при тестировании.
Отключение обработчика и обработка ошибок
Отключение — это половина правильной работы с таймером:
ОтключитьОбработчикОжидания("ПроверитьСостояниеЗадания");
Вызывайте ОтключитьОбработчикОжидания в трёх ситуациях:
- 🎯 задача, ради которой подключался таймер, выполнена (задание завершилось);
- 🚪 обработчик привязан к форме, а форма закрывается;
- 🔁 нужно сменить интервал — тогда достаточно повторного
ПодключитьОбработчикОжидания, отдельное отключение не обязательно.
Отдельно — про закрытие формы. Если таймер привязан к форме, снимите его в событии ПередЗакрытием. Иначе платформа попробует вызвать процедуру формы, которой уже нет, и в лог упадёт ошибка:
&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
ОтключитьОбработчикОжидания("ОбновитьДанныеНаФорме");
КонецПроцедуры
Вызывать ОтключитьОбработчикОжидания для процедуры, которая и так не подключена, безопасно — ошибки не будет. Так что перестраховаться дешевле, чем оставить висящий таймер.
Теперь про ошибки. Если внутри процедуры-обработчика возникнет исключение, оно всплывёт на клиент как обычная ошибка — и пользователь увидит её при каждом срабатывании, пока таймер подключён. Поэтому рискованный код оборачивают в Попытка:
&НаКлиенте
Процедура ПроверитьСостояниеЗадания()
Попытка
Если ЗаданиеЗавершено(ИдентификаторЗадания) Тогда
ОтключитьОбработчикОжидания("ПроверитьСостояниеЗадания");
ОбработатьРезультатЗадания();
КонецЕсли;
Исключение
ОтключитьОбработчикОжидания("ПроверитьСостояниеЗадания");
ПоказатьПредупреждение("Не удалось проверить задание: "
+ ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
Две частые причины ошибок при срабатывании:
- Имя процедуры не найдено. Строка в
ПодключитьОбработчикОжиданияне совпадает с именем процедуры (опечатка, другой регистр не критичен, но лишний пробел — да), либо процедура объявлена без&НаКлиенте. - У процедуры есть параметры. Обработчик вызывает процедуру без аргументов — если в объявлении есть параметры, будет ошибка. Уберите их или заведите промежуточную процедуру-обёртку.
Рабочие приёмы и как не нагрузить клиент
Несколько правил, которые отличают аккуратный код от «таймера, который тормозит базу»:
| Приём | Зачем |
|---|---|
| Интервал не меньше реально нужного | Опрос каждую секунду — это серверный вызов каждую секунду на каждого пользователя |
| Адаптивный интервал (1 → 2 → 5 сек) | Долгое задание не нужно опрашивать так же часто, как только что запущенное |
| Тяжёлый код — на сервер | Тело обработчика выполняется в основном потоке; длинная операция подвесит интерфейс |
Однократно = Истина для разовых действий | Не придётся вручную отключать таймер после одного срабатывания |
| Отключать по завершении | «Забытый» обработчик продолжает слать вызовы, пока открыта форма |
Пример адаптивного опроса — наращиваем интервал, чтобы не долбить сервер:
&НаКлиенте
Процедура ПроверитьСостояниеЗадания()
Если ЗаданиеЗавершено(ИдентификаторЗадания) Тогда
ОтключитьОбработчикОжидания("ПроверитьСостояниеЗадания");
ОбработатьРезультатЗадания();
Иначе
Если ТекущийИнтервал < 10 Тогда
ТекущийИнтервал = ТекущийИнтервал + 2;
ПодключитьОбработчикОжидания("ПроверитьСостояниеЗадания", ТекущийИнтервал);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Здесь повторный ПодключитьОбработчикОжидания переустанавливает тот же обработчик с бо́льшим интервалом — новый таймер не плодится. Счётчик ТекущийИнтервал — это реквизит формы; перед запуском задания его задают начальным значением (например, 1).
Чтобы пользователь во время опроса видел, что процесс идёт, а не завис, показывайте неблокирующее оповещение методом ПоказатьОповещениеПользователя. Оно не прерывает работу и не требует клика — в отличие от Предупреждение, которое заблокировало бы клиент и вместе с ним сам обработчик.
И последнее про предсказуемость. Обработчик ожидания не гарантирует срабатывание точно по расписанию: он вызывается в простое клиента. Если пользователь открыл модальное окно или выполняется длинный синхронный вызов — очередной вызов сдвинется. Для действительно точного по времени поведения обработчик ожидания не предназначен; его сила в простоте и лёгком фоновом опросе.