Таймеры и временные интервалы в 1С 8.3: все рабочие способы

· 9 мин

Содержание

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

Ниже — конкретный код для каждого случая, как остановить таймер и чем интервальный обработчик отличается от регламентного задания в клиент-серверном и файловом режиме.

Обработчик ожидания: таймер прямо на форме

Основной инструмент для периодических действий в интерфейсе — метод формы ПодключитьОбработчикОжидания. Синтаксис:

ПодключитьОбработчикОжидания(<ИмяПроцедуры>, <Интервал>, <Однократно>)
  • ИмяПроцедуры — строка, имя клиентской процедуры-обработчика без параметров, объявленной в модуле формы.
  • Интервал — число секунд между вызовами. Для обработчика формы допустимы дробные значения (например, 0.2), для глобального обработчика минимум — 1 секунда.
  • Однократно — необязательный. Истина — сработает один раз, Ложь (по умолчанию) — повторяется до отключения.

Процедура-обработчик помечается директивой &НаКлиенте и ничего не принимает. Вот секундомер «мм:сс» на декорации формы. Счётчик храним в числовом реквизите формы СчётчикСекунд:

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    СчётчикСекунд = 0;
    ПодключитьОбработчикОжидания("ТикТаймера", 1);
КонецПроцедуры

&НаКлиенте
Процедура ТикТаймера()
    СчётчикСекунд = СчётчикСекунд + 1;
    Минуты  = Цел(СчётчикСекунд / 60);
    Секунды = СчётчикСекунд % 60;
    Элементы.ПолеТаймер.Заголовок = ДвеЦифры(Минуты) + ":" + ДвеЦифры(Секунды);
КонецПроцедуры

&НаКлиенте
Функция ДвеЦифры(Знач Число)
    Стр = Строка(Число);
    Возврат ?(СтрДлина(Стр) < 2, "0" + Стр, Стр);
КонецФункции

Чтобы собрать такой таймер на форме с нуля:

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

Обработчик срабатывает только когда клиент свободен. Если пользователь открыл модальное окно или выполняется длинный серверный вызов, тик произойдёт позже — абсолютной точности «по часам» ждать не стоит.

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

Несколько таймеров на одной форме. Ограничения на число обработчиков нет — можно подключить несколько процедур с разными интервалами (например, одна обновляет часы раз в секунду, другая опрашивает сервер раз в 30 секунд). Каждая живёт и отключается независимо по своему имени.

Есть и глобальный обработчик ожидания — тот же метод вызывается в контексте всего приложения и не привязан к конкретной форме. Он удобен для фоновых проверок на уровне сеанса (например, опрос состояния), но его минимальный интервал — 1 секунда, и дробные значения он не принимает. Главное отличие от формы: такой обработчик не исчезнет при закрытии окна и будет работать, пока открыт сеанс, — отключать его нужно самостоятельно.

Паузы и задержки без зависания интерфейса

Частая ошибка новичков — сделать паузу циклом по текущему времени:

// ТАК ДЕЛАТЬ НЕЛЬЗЯ — интерфейс замрёт на 5 секунд
НачалоПаузы = ТекущаяДата();
Пока ТекущаяДата() - НачалоПаузы < 5 Цикл
    // пустое ожидание
КонецЦикла;

Такой «активный цикл» полностью занимает клиентский поток: кнопки не нажимаются, окно не перерисовывается, курсор крутится. В 1С нет функции Sleep, и имитировать её циклом нельзя.

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

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

&НаКлиенте
Процедура ПродолжитьПослеПаузы()
    // этот код выполнится через 3 секунды, не блокируя интерфейс
    Сообщить("Прошло 3 секунды");
КонецПроцедуры

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

Разница в поведении принципиальна. Активный цикл по времени даёт ровно ту задержку, которую вы указали, но ценой полного зависания интерфейса. Однократный обработчик ожидания возвращает управление мгновенно, а ваше действие выполняется «потом» — пользователь всё это время спокойно работает с формой. Для интерфейса второй вариант верен почти всегда.

Отдельно стоит помнить: интервал однократного обработчика — это не точная задержка, а «не раньше чем». Если в момент срабатывания клиент занят, тик сдвинется. Для секундных пауз в интерфейсе это незаметно, но закладываться на миллисекундную точность нельзя.

Серверный таймер: регламентные и фоновые задания

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

Схема такая:

  1. В конфигураторе в ветке Общие → Регламентные задания создаёте регламентное задание.
  2. Указываете имя метода-обработчика — экспортную процедуру в серверном (не глобальном клиентском) общем модуле.
  3. Задаёте расписание: периодичность, дни недели, время начала и окончания, интервал повтора в течение дня.

Фактическую работу выполняет связанное фоновое задание — отдельный серверный поток, который кластер запускает в назначенное время. В коде задания нет интерфейса: только серверная логика и запись результата (в регистр, справочник, журнал регистрации).

Важно, в каком режиме работает база:

  • Клиент-серверный режим — расписание отрабатывает сам кластер серверов, автоматически, даже если ни один пользователь не в системе.
  • Файловый режим — регламентные задания сами не запускаются. Нужен постоянно открытый сеанс, который периодически инициирует их обработку. Поэтому в типовых конфигурациях на файловой базе под регламентные операции держат отдельный «технологический» сеанс.

Расписание удобнее задавать через стандартную форму настройки (в клиент-серверной базе — через консоль администрирования кластера или обработку из состава конфигурации), а не кодом: там наглядно видны периоды и повторы.

В расписании задаются основные параметры:

  • 📅 Периодичность — каждый день, через N дней, в определённые дни недели или числа месяца.
  • ⏰ Время начала и окончания — окно, в котором задание может стартовать.
  • 🔁 Интервал повтора в течение дня — например, повторять каждый час внутри рабочего времени.

Так один и тот же механизм закрывает и «раз в сутки ночью», и «каждые 15 минут с 9 до 18». Фактический запуск отдаёт кластер серверов , вам остаётся следить за результатом.

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

Какой способ выбрать под задачу

Три механизма закрывают разные сценарии. Ориентир:

СпособКогда применятьГде работаетЧастота
Обработчик ожидания формыОбновить данные на экране, секундомер, автосохранение черновикаКлиент, пока открыта формаОт долей секунды
Глобальный обработчик ожиданияФоновый опрос на уровне сеанса без привязки к формеКлиент, пока открыт сеансОт 1 секунды
Регламентное заданиеПериодическая серверная операция по расписаниюСервер, независимо от пользователейОт минут и реже

Коротко по выбору:

Что должен делать ваш таймер?

Как остановить таймер и управлять его жизненным циклом

Повторяющийся обработчик будет тикать, пока его явно не отключить:

ОтключитьОбработчикОжидания("ТикТаймера");

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

Ключевые правила управления:

  • 🔁 Пауза/продолжение. Отдельного «паузнуть» нет. Чтобы приостановить, вызовите ОтключитьОбработчикОжидания, чтобы возобновить — снова ПодключитьОбработчикОжидания с тем же именем.
  • 🔄 Смена интервала. Чтобы ускорить или замедлить таймер, отключите обработчик и подключите заново с новым интервалом. Повторное подключение того же имени заменяет прежнюю настройку.
  • 🧹 Закрытие формы. Обработчики формы прекращают работу вместе с закрытием формы — отдельно чистить их обычно не нужно. А вот глобальный обработчик живёт до конца сеанса: его отключайте сами, иначе он продолжит вызывать процедуру.
  • ✅ Однократный обработчик снимается автоматически после единственного срабатывания — отключать его не требуется.

Если таймер должен стартовать не при открытии, а по кнопке, держите рядом две команды — «Старт» (подключает обработчик) и «Стоп» (отключает). Так жизненный цикл очевиден и пользователю, и тому, кто будет читать код.

Производительность: как не перегрузить систему

Таймеры легко превратить в источник тормозов. Несколько практических ограничений.

Не ставьте слишком маленький интервал. Тик раз в 0,2 секунды с серверным вызовом внутри — это пять обращений к серверу в секунду от каждого клиента. На десятках сеансов это ощутимая нагрузка. Для визуального счётчика секунды более чем достаточно; реальные данные с сервера опрашивайте раз в несколько секунд или реже.

Выносите тяжёлую логику с клиентского тика. Обработчик ожидания исполняется на клиенте. Если внутри идёт запрос к базе, каждый тик — это серверный вызов. Делайте в обработчике минимум: один короткий вызов, а не выборку больших объёмов.

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

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

Регламентные задания не ставьте встык. Если десяток заданий стартует в 03:00, они конкурируют за рабочие процессы кластера. Разнесите время старта и учитывайте, что число одновременных фоновых заданий ограничено настройками кластера.

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

Проверка перед внедрением таймера
Выполнено: 0 / 5

Частые вопросы

Почему мой обработчик ожидания вообще не срабатывает?
Две типичные причины: процедура объявлена без директивы &НаКлиенте или у неё есть параметры (обработчик должен быть без параметров), либо имя в ПодключитьОбработчикОжидания не совпадает с именем процедуры. Имя передаётся строкой — опечатка не вызовет ошибку компиляции, обработчик просто не вызовется.
Можно ли сделать интервал меньше секунды?
Для обработчика формы — да, допустимы дробные значения, например 0.2 секунды. Глобальный обработчик приложения работает с интервалом не меньше 1 секунды.
Таймер продолжает тикать после закрытия формы — это нормально?
Для обработчика, подключённого на форме, нет — он снимается вместе с формой. Если тики продолжаются, скорее всего вы использовали глобальный обработчик: его нужно отключать вручную через ОтключитьОбработчикОжидания.
Регламентное задание не запускается в файловой базе. Почему?
В файловом режиме кластера нет, и расписание само не отрабатывает. Нужен постоянно открытый сеанс, который инициирует обработку заданий. В клиент-серверной базе этим занимается кластер автоматически.
Как сделать обратный отсчёт, а не секундомер?
Та же схема с обработчиком ожидания, но счётчик уменьшайте и при достижении нуля вызывайте ОтключитьОбработчикОжидания, затем выполняйте нужное действие (сообщение, закрытие формы, запуск операции).