Таймеры отложенного выполнения
Можно настроить таймер, чтобы вызвать функцию в указанное время в будущем или по истечении определённого периода бездействия. Таймер — это специальный объект, в котором хранится информация о времени следующего вызова и вызываемой функции.
- Функция: timerp object
Эта предикатная функция возвращает значение, отличное от
nil, еслиobjectявляется таймером.
Emacs не может запускать таймеры в произвольный момент выполнения программы на Lisp; он может запускать их только тогда, когда Emacs мог бы принимать вывод от подпроцесса: а именно, во время ожидания или внутри некоторых примитивных функций, таких как sit-for или read-event, которые могут ожидать. Поэтому выполнение таймера может задержаться, если Emacs занят. Однако, когда Emacs простаивает, время выполнения очень точно.
Перед вызовом функции таймера Emacs связывает inhibit-quit со значением t, поскольку выход из многих функций таймера по прерыванию может оставить систему в несогласованном состоянии. Обычно это не вызывает проблем, так как большинство функций таймера не выполняют много работы. Более того, таймер, вызывающий функцию, выполнение которой занимает значительное время, скорее всего, будет раздражать. Если функции таймера необходимо разрешить прерывание, она должна использовать with-local-quit (см. Прерывание). Например, если функция таймера вызывает accept-process-output для получения вывода от внешнего процесса, этот вызов следует обернуть в with-local-quit, чтобы C-g срабатывал, если внешний процесс зависнет.
Обычно функциям таймера не следует изменять содержимое буфера. Если они это делают, то обычно должны вызывать undo-boundary до и после изменения буфера, чтобы отделить изменения таймера от изменений, внесённых пользовательскими командами, и не допустить чрезмерного увеличения одной записи отмены.
Функциям таймера также следует избегать вызова функций, заставляющих Emacs ожидать, таких как sit-for (см. Ожидание истечения времени или ввода). Это может привести к непредсказуемым последствиям, поскольку во время ожидания могут запускаться другие таймеры (или даже тот же таймер). Если функция таймера должна выполнить действие по истечении определённого времени, она может сделать это, запланировав новый таймер.
Если функция таймера выполняет операцию с удалённым файлом, она может конфликтовать с уже выполняющейся операцией с удалённым файлом того же соединения. Такие конфликты обнаруживаются и приводят к ошибке remote-file-error (см. Стандартные ошибки). Этого следует избегать, обернув тело функции таймера в
(ignore-error remote-file-error ...)
Если функция таймера вызывает функции, которые могут изменить данные о совпадении, ей следует сохранить и восстановить эти данные. См. Сохранение и восстановление данных о совпадении.
- Команда: run-at-time time repeat function &rest args
-
Эта функция настраивает таймер, который вызывает функцию function с аргументами args во время time. Если repeat — число (целое или с плавающей точкой), таймер планируется для повторного запуска каждые repeat секунд после time. Если repeat равно
nil, таймер срабатывает только один раз.time может задавать абсолютное или относительное время.
Абсолютное время можно задать строкой в одном из ограниченного числа форматов; оно считается временем сегодня, даже если указанное время уже прошло. Допустимы следующие формы: ‘xxxx’, ‘x:xx’ или ‘xx:xx’ (24-часовой формат), а также ‘xxam’, ‘xxAM’, ‘xxpm’, ‘xxPM’, ‘xx:xxam’, ‘xx:xxAM’, ‘xx:xxpm’ или ‘xx:xxPM’. Для разделения часов и минут вместо двоеточия можно использовать точку.
Чтобы задать относительное время строкой, укажите числа с единицами измерения. Например:
- ‘1 min’
означает через 1 минуту.
- ‘1 min 5 sec’
означает через 65 секунд.
- ‘1 min 2 sec 3 hour 4 day 5 week 6 fortnight 7 month 8 year’
означает ровно через 103 месяца, 123 дня и 10862 секунды.
Для относительных значений времени Emacs считает месяц равным ровно тридцати дням, а год — ровно 365,25 дня.
Не все удобные форматы являются строками. Если time — число (целое или с плавающей точкой), оно задаёт относительное время в секундах. Результат
encode-timeтакже можно использовать для задания абсолютного значения time.В большинстве случаев repeat не влияет на время первого вызова — оно задаётся только параметром time. Есть одно исключение: если time равно
t, таймер срабатывает всякий раз, когда время кратно repeat секундам, отсчитываемым от эпохи. Это полезно для таких функций, какdisplay-time. Например, следующий код будет запускать function в начале каждой минуты (например, в ‘11:03:00’, ‘11:04:00’ и т. д.):(run-at-time t 60 function)
Если в момент запланированного срабатывания таймера Emacs не получал процессорного времени (например, если система была занята другим процессом или компьютер находился в спящем или приостановленном состоянии), таймер сработает, как только Emacs возобновит работу и перейдёт в состояние простоя.
Функция
run-at-timeвозвращает значение таймера, идентифицирующее конкретное запланированное действие в будущем. Это значение можно использовать для вызоваcancel-timer(см. ниже).
- Команда: run-with-timer secs repeat function &rest args
Эта функция полностью эквивалентна
run-at-time(пояснение параметров см. в её описании; secs передаётся этой функции в качестве time), но предназначена для случаев, когда задержка задаётся в секундах.
Предполагается, что повторяющийся таймер должен срабатывать каждые repeat секунд, однако следует помнить, что любой вызов таймера может произойти с опозданием. Опоздание одного срабатывания не влияет на запланированное время следующего. Например, если Emacs достаточно долго занят вычислениями, чтобы пропустить три запланированных срабатывания таймера, а затем начинает ожидать, он немедленно вызовет функцию таймера три раза подряд (при условии, что между этими вызовами не сработают другие таймеры). Если нужно, чтобы таймер запускался не раньше чем через n секунд после предыдущего вызова, не используйте аргумент repeat. Вместо этого функция таймера должна явно запланировать его повторный запуск.
- Пользовательский параметр: timer-max-repeats
Значение этой переменной задаёт максимальное число последовательных вызовов функции таймера, если многие ранее запланированные вызовы неизбежно задержались.
- Макрос: with-timeout (seconds timeout-forms…) body…
-
Выполняет body, но прекращает выполнение по истечении seconds секунд. Если body завершается до истечения времени,
with-timeoutвозвращает значение последней формы в body. Если же выполнение body прерывается по тайм-ауту,with-timeoutвыполняет все формы timeout-forms и возвращает значение последней из них.Этот макрос работает, устанавливая таймер, который срабатывает через seconds секунд. Если body завершается до этого момента, макрос отменяет таймер. Если таймер срабатывает, он прерывает выполнение body, а затем выполняет формы timeout-forms.
Поскольку таймеры могут запускаться внутри программы на Lisp только при вызове программой примитива, способного ожидать,
with-timeoutне может прекратить выполнение body посреди вычисления — это произойдёт только при вызове одного из таких примитивов. Поэтому используйтеwith-timeoutтолько с body, который ожидает ввода, а не выполняет длительные вычисления. К примитивам, ожидающим ввода, относятсяsit-for,sleep-for,accept-process-outputи некоторые другие.
Функция y-or-n-p-with-timeout предоставляет простой способ использовать таймер, чтобы не ждать ответа слишком долго. См. Запросы с ответом «да» или «нет».
- Функция: cancel-timer timer
Отменяет запрошенное действие для timer, который должен быть таймером — обычно таким, который ранее вернула функция
run-at-timeилиrun-with-idle-timer. Это отменяет действие соответствующего вызова одной из этих функций; наступление указанного времени не приведёт ни к каким особым действиям.
Команда list-timers выводит список всех активных таймеров. Команда c (timer-list-cancel) отменяет таймер в строке под точкой. Список можно сортировать по столбцам с помощью команды S (tabulated-list-sort).
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Timers.html