Обработчик ожидания. Нюансы
ПодключитьОбработчикОжидания: некоторые подробности и особенности работы
- Описание
- Подробнее
Описание
Механизм подключения обработчика ожидания известен с 8.0, описан в Синтакс-помощнике и десятках публикаций. По сути, это механизм, реализующий псевдо-параллельный вызов процедур клиентского контекста сеанса с заданной периодичностью либо однократно.
С точки зрения языка 1С, это две процедуры глобального контекста сеанса: ПодключитьОбработчикОжидания и ОтключитьОбработчикОжидания. Пересказывать хелп не будем, отметим только, что сложился стереотип, будто однократность применима лишь для таймаута менее 1 секунды; но реально однократный вызов может использовать любой таймаут.
С точки зрения платформы, это поддерживаемая процессом rphost, единая для сеанса, виртуальная таблица ключей, таймаутов и текущих значений таймера.
* Ключ — хеш от ID модуля, откуда был выполнен вызов, ID модуля вызываемой процедуры обработчика, и имени процедуры обработчика. Идентификаторы модулей можно увидеть, выгрузив конфигурацию в файлы.
* Таймаут — число, рассчитывается в миллисекундах.
* Текущее значение таймера — момент предыдущего срабатывания, дата/время с миллисекундами. Таймеры отталкиваются от текущей даты/времени сеанса в момент компиляции подключения обработчика или реинициализации таблицы.
Эта таблица обслуживается специальным обработчиком, который не является сервисом кластера, а просто часть механизма платформы. Обработчик не учитывает успешность вызова и выполнения вызываемой процедуры.
Эта таблица не относится к сеансовым данным (косвенно упоминается в руководствах лишь как "прочие данные сеанса"), при обращениях к серверу и ряде других операций значения таймеров сбрасываются, и очередной вызов происходит гораздо раньше, чем истёк таймаут.
Реинициализация этой таблицы происходит при любом "возврате на клиент", т.е. при передаче менеджером кластера управления клиенту (штатного, по службе кластера, или по исключению) и передаче хранимых для рабочего процесса сеансовых данных. Штатно — понятно; по службе кластера — имеется в виду служба отладчика, т.е. продолжение действия по прохождении точки останова; по исключению — только если ошибка была восстановимая, касалась сервера либо обмена клиент-сервер и (если запуск был из формы) не касалась блокировок этой формы.
Прекращение обработки конкретной записи этой таблицы происходит, когда из стека исчезает указатель в памяти на область, хранящую тот контекст (форму/модуль и их кэш), откуда выполнялось подключение обработчика (а вовсе не тот контекст, где располагается вызываемая по таймауту процедура, как иногда ошибочно пишут). Грубо говоря для большинства случаев, обработчик стопится, когда закрывается форма или приложение, откуда он стартовал.
Существенно различно в разных релизах до 8.3.11 ведёт себя при остановке на точке останова; в текущих релизах всегда сбрасываются таймауты и сразу стартует обработка заново — и по прохождении останова, и при остановке по ошибке, если ошибка была обработана. Не важно, где находится точка останова — в действиях, вызванных обработчиком, или в других действиях, реинициализация делается всегда.
Поведение аналогично и для файловых, и для клиент-серверных ИБ. Поведение в клиенте тестирования аналогично поведению в обычных запусках клиента. Поведение в веб-клиенте формально одинаковое, но известны случаи, когда в браузере "Safari" таймауты "сжимались" относительно ожидаемого в состоянии "покоя" клиента, т.е. написано было 60, а реально срабатывало через 45-48 секунд.
Сеансы и обработчики. До версии 8.3.7.2008 наличие хотя бы одного сработавшего обработчика ожидания вынуждало сеанс никогда не "засыпать" и даже не считаться пассивным. В некоторых релизах 8.3.9 и 8.3.11 запущенные обработчики не мешали сеансу засыпать и быть впоследствии удалённым, но продолжали работать, что проверено выполнением записи из их процедуры в клиентский файл на локальном ПК (занята ли бывала при этом лицензия, сведений нет) — фиксировать активность сеанса средствами ЖР нельзя было потому, что запись в ЖР это обращение к сервису кластера и вообще к серверу.
Наличие назначенного сеансу соединения никак ни на что не влияло и не влияет. Соединение может пропасть, а обработчик продолжит свою работу.
В настоящее время запущенные обработчики в понятие "активность пользователя" (не юзера-за-экраном, а именно пользователя в админском смысле) не входят. Сведений о том, передаётся ли прежняя сохранённая таблица обработчиков сеансу кластером при возобновлении его работы, или просто реинициализируется, нет.
Из устройства этого механизма следует ряд нюансов.
1. Обработчик можно запускать и останавливать в форме, экземпляр которой создан, но не открыт; в любой момент, пока её контекст есть в некоей переменной. Запускать и останавливать придётся отдельными экспортными процедурами, т.к. обращение "НеоткрытаяФорма.ПодключитьОбработчикОжидания" игнорируется без генерации исключения. С уничтожением переменной формы останавливается и обработчик — поэтому следует быть внимательными, чтобы после закрытия запустившей формы или команды не случилось зависания этой переменной в памяти сеанса.

