Таймеры и временные интервалы в 1С 8.3: все рабочие способы
Содержание
Таймер на форме делают методом ПодключитьОбработчикОжидания — он раз в заданный интервал вызывает вашу процедуру на клиенте. Серверный таймер (по расписанию, без открытой формы) — это регламентное задание. Паузу в коде через цикл с проверкой времени делать нельзя: интерфейс зависнет.
Ниже — конкретный код для каждого случая, как остановить таймер и чем интервальный обработчик отличается от регламентного задания в клиент-серверном и файловом режиме.
Обработчик ожидания: таймер прямо на форме
Основной инструмент для периодических действий в интерфейсе — метод формы ПодключитьОбработчикОжидания. Синтаксис:
ПодключитьОбработчикОжидания(<ИмяПроцедуры>, <Интервал>, <Однократно>)
ИмяПроцедуры— строка, имя клиентской процедуры-обработчика без параметров, объявленной в модуле формы.Интервал— число секунд между вызовами. Для обработчика формы допустимы дробные значения (например,0.2), для глобального обработчика минимум — 1 секунда.Однократно— необязательный.Истина— сработает один раз,Ложь(по умолчанию) — повторяется до отключения.
Процедура-обработчик помечается директивой &НаКлиенте и ничего не принимает. Вот секундомер «мм:сс» на декорации формы. Счётчик храним в числовом реквизите формы СчётчикСекунд:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
СчётчикСекунд = 0;
ПодключитьОбработчикОжидания("ТикТаймера", 1);
КонецПроцедуры
&НаКлиенте
Процедура ТикТаймера()
СчётчикСекунд = СчётчикСекунд + 1;
Минуты = Цел(СчётчикСекунд / 60);
Секунды = СчётчикСекунд % 60;
Элементы.ПолеТаймер.Заголовок = ДвеЦифры(Минуты) + ":" + ДвеЦифры(Секунды);
КонецПроцедуры
&НаКлиенте
Функция ДвеЦифры(Знач Число)
Стр = Строка(Число);
Возврат ?(СтрДлина(Стр) < 2, "0" + Стр, Стр);
КонецФункции
Чтобы собрать такой таймер на форме с нуля:
- В конфигураторе откройте форму, на вкладке Реквизиты добавьте числовой реквизит
СчётчикСекунд. - На вкладке Элементы добавьте поле надписи (декорацию) и назовите его
ПолеТаймер— в него будем выводить время. - В модуле формы напишите процедуры из примера выше и привяжите подключение обработчика к нужному событию:
ПриОткрытии, нажатию кнопки «Старт» или команде.
Обработчик срабатывает только когда клиент свободен. Если пользователь открыл модальное окно или выполняется длинный серверный вызов, тик произойдёт позже — абсолютной точности «по часам» ждать не стоит.
Передача данных в обработчик. Процедура не принимает параметров, поэтому значения, которые ей нужны, храните в реквизитах формы (как СчётчикСекунд выше) или в переменных модуля формы. Это стандартный приём: обработчик читает состояние, меняет его и при необходимости сам решает, продолжать ли счёт.
Несколько таймеров на одной форме. Ограничения на число обработчиков нет — можно подключить несколько процедур с разными интервалами (например, одна обновляет часы раз в секунду, другая опрашивает сервер раз в 30 секунд). Каждая живёт и отключается независимо по своему имени.
Есть и глобальный обработчик ожидания — тот же метод вызывается в контексте всего приложения и не привязан к конкретной форме. Он удобен для фоновых проверок на уровне сеанса (например, опрос состояния), но его минимальный интервал — 1 секунда, и дробные значения он не принимает. Главное отличие от формы: такой обработчик не исчезнет при закрытии окна и будет работать, пока открыт сеанс, — отключать его нужно самостоятельно.
Паузы и задержки без зависания интерфейса
Частая ошибка новичков — сделать паузу циклом по текущему времени:
// ТАК ДЕЛАТЬ НЕЛЬЗЯ — интерфейс замрёт на 5 секунд
НачалоПаузы = ТекущаяДата();
Пока ТекущаяДата() - НачалоПаузы < 5 Цикл
// пустое ожидание
КонецЦикла;
Такой «активный цикл» полностью занимает клиентский поток: кнопки не нажимаются, окно не перерисовывается, курсор крутится. В 1С нет функции Sleep, и имитировать её циклом нельзя.
Правильный приём — отложить продолжение через однократный обработчик ожидания. Код до паузы выполняется, управление возвращается пользователю, а нужное действие запускается через заданный интервал:
&НаКлиенте
Процедура ЗапуститьСОтсрочкой()
// здесь — то, что нужно сделать сразу
ПодключитьОбработчикОжидания("ПродолжитьПослеПаузы", 3, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ПродолжитьПослеПаузы()
// этот код выполнится через 3 секунды, не блокируя интерфейс
Сообщить("Прошло 3 секунды");
КонецПроцедуры
Если задержка нужна между шагами в серверном коде (например, подождать ответа внешней системы), используют асинхронную модель с описанием оповещения (ОписаниеОповещения) — продолжение вызывается по готовности результата, а не по таймеру. Блокирующих пауз на сервере в многопользовательской базе избегают: рабочий процесс занят и для остальных сеансов.
Разница в поведении принципиальна. Активный цикл по времени даёт ровно ту задержку, которую вы указали, но ценой полного зависания интерфейса. Однократный обработчик ожидания возвращает управление мгновенно, а ваше действие выполняется «потом» — пользователь всё это время спокойно работает с формой. Для интерфейса второй вариант верен почти всегда.
Отдельно стоит помнить: интервал однократного обработчика — это не точная задержка, а «не раньше чем». Если в момент срабатывания клиент занят, тик сдвинется. Для секундных пауз в интерфейсе это незаметно, но закладываться на миллисекундную точность нельзя.
Серверный таймер: регламентные и фоновые задания
Когда действие должно выполняться по расписанию и без открытой формы (ночной пересчёт, выгрузка, проверка почты), таймер на форме не подходит — он живёт только пока открыт сеанс с формой. Для этого есть регламентные задания.
Схема такая:
- В конфигураторе в ветке
Общие → Регламентные заданиясоздаёте регламентное задание. - Указываете имя метода-обработчика — экспортную процедуру в серверном (не глобальном клиентском) общем модуле.
- Задаёте расписание: периодичность, дни недели, время начала и окончания, интервал повтора в течение дня.
Фактическую работу выполняет связанное фоновое задание — отдельный серверный поток, который кластер запускает в назначенное время. В коде задания нет интерфейса: только серверная логика и запись результата (в регистр, справочник, журнал регистрации).
Важно, в каком режиме работает база:
- Клиент-серверный режим — расписание отрабатывает сам кластер серверов, автоматически, даже если ни один пользователь не в системе.
- Файловый режим — регламентные задания сами не запускаются. Нужен постоянно открытый сеанс, который периодически инициирует их обработку. Поэтому в типовых конфигурациях на файловой базе под регламентные операции держат отдельный «технологический» сеанс.
Расписание удобнее задавать через стандартную форму настройки (в клиент-серверной базе — через консоль администрирования кластера или обработку из состава конфигурации), а не кодом: там наглядно видны периоды и повторы.
В расписании задаются основные параметры:
- 📅 Периодичность — каждый день, через N дней, в определённые дни недели или числа месяца.
- ⏰ Время начала и окончания — окно, в котором задание может стартовать.
- 🔁 Интервал повтора в течение дня — например, повторять каждый час внутри рабочего времени.
Так один и тот же механизм закрывает и «раз в сутки ночью», и «каждые 15 минут с 9 до 18». Фактический запуск отдаёт кластер серверов , вам остаётся следить за результатом.
Контроль выполнения. Результат и ошибки фоновых заданий видны в журнале регистрации — отбирайте события по регламентным заданиям, чтобы понять, отработало ли задание и не завершилось ли с ошибкой. Тяжёлую логику внутри задания оборачивайте в обработку исключений (Попытка … Исключение … КонецПопытки) и пишите понятное сообщение в журнал: если фоновый поток упадёт молча, пользователь об этом не узнает.
Какой способ выбрать под задачу
Три механизма закрывают разные сценарии. Ориентир:
| Способ | Когда применять | Где работает | Частота |
|---|---|---|---|
| Обработчик ожидания формы | Обновить данные на экране, секундомер, автосохранение черновика | Клиент, пока открыта форма | От долей секунды |
| Глобальный обработчик ожидания | Фоновый опрос на уровне сеанса без привязки к форме | Клиент, пока открыт сеанс | От 1 секунды |
| Регламентное задание | Периодическая серверная операция по расписанию | Сервер, независимо от пользователей | От минут и реже |
Коротко по выбору:
ПриОткрытии и отключите при закрытии.Однократно = Истина). Активный цикл по времени не использовать.ОписаниеОповещения, а не таймер.Как остановить таймер и управлять его жизненным циклом
Повторяющийся обработчик будет тикать, пока его явно не отключить:
ОтключитьОбработчикОжидания("ТикТаймера");
Метод принимает имя той же процедуры, что передавали при подключении. Несколько разных обработчиков на одной форме — нормальная ситуация: каждый отключается по своему имени.
Ключевые правила управления:
- 🔁 Пауза/продолжение. Отдельного «паузнуть» нет. Чтобы приостановить, вызовите
ОтключитьОбработчикОжидания, чтобы возобновить — сноваПодключитьОбработчикОжиданияс тем же именем. - 🔄 Смена интервала. Чтобы ускорить или замедлить таймер, отключите обработчик и подключите заново с новым интервалом. Повторное подключение того же имени заменяет прежнюю настройку.
- 🧹 Закрытие формы. Обработчики формы прекращают работу вместе с закрытием формы — отдельно чистить их обычно не нужно. А вот глобальный обработчик живёт до конца сеанса: его отключайте сами, иначе он продолжит вызывать процедуру.
- ✅ Однократный обработчик снимается автоматически после единственного срабатывания — отключать его не требуется.
Если таймер должен стартовать не при открытии, а по кнопке, держите рядом две команды — «Старт» (подключает обработчик) и «Стоп» (отключает). Так жизненный цикл очевиден и пользователю, и тому, кто будет читать код.
Производительность: как не перегрузить систему
Таймеры легко превратить в источник тормозов. Несколько практических ограничений.
Не ставьте слишком маленький интервал. Тик раз в 0,2 секунды с серверным вызовом внутри — это пять обращений к серверу в секунду от каждого клиента. На десятках сеансов это ощутимая нагрузка. Для визуального счётчика секунды более чем достаточно; реальные данные с сервера опрашивайте раз в несколько секунд или реже.
Выносите тяжёлую логику с клиентского тика. Обработчик ожидания исполняется на клиенте. Если внутри идёт запрос к базе, каждый тик — это серверный вызов. Делайте в обработчике минимум: один короткий вызов, а не выборку больших объёмов.
Длинные операции — в фоновое задание, а не в таймер. Если по расписанию нужно обработать много данных, запускайте фоновое задание и проверяйте его состояние, а не крутите долгий цикл внутри обработчика ожидания.
Следите за числом одновременных обработчиков. Несколько форм, каждая со своим секундным таймером, суммарно дают поток вызовов. Отключайте обработчики, которые больше не нужны.
Регламентные задания не ставьте встык. Если десяток заданий стартует в 03:00, они конкурируют за рабочие процессы кластера. Разнесите время старта и учитывайте, что число одновременных фоновых заданий ограничено настройками кластера.
Не держите таймер ради таймера. Если данные на форме меняются по событию (пользователь что-то сохранил, пришло оповещение), лучше обновлять форму по этому событию, а не опрашивать сервер по кругу. Таймер оправдан там, где нет внешнего сигнала и приходится периодически проверять состояние самому — например, ждать завершения долгой операции в фоновом задании. Во всех остальных случаях лишний интервальный опрос только нагружает сервер и сеть, не давая пользователю ничего нового.
Частые вопросы
Почему мой обработчик ожидания вообще не срабатывает?
&НаКлиенте или у неё есть параметры (обработчик должен быть без параметров), либо имя в ПодключитьОбработчикОжидания не совпадает с именем процедуры. Имя передаётся строкой — опечатка не вызовет ошибку компиляции, обработчик просто не вызовется.Можно ли сделать интервал меньше секунды?
0.2 секунды. Глобальный обработчик приложения работает с интервалом не меньше 1 секунды.Таймер продолжает тикать после закрытия формы — это нормально?
ОтключитьОбработчикОжидания.Регламентное задание не запускается в файловой базе. Почему?
Как сделать обратный отсчёт, а не секундомер?
ОтключитьОбработчикОжидания, затем выполняйте нужное действие (сообщение, закрытие формы, запуск операции).