Таймеры для отложенного выполнения
Вы можете настроить таймер, чтобы вызвать функцию в указанное будущее время или после определенного периода бездействия. Таймер — это специальный объект, который хранит информацию о времени следующего вызова и вызываемой функции.
- Функция: timerp объект
Эта функция-предикат возвращает не-
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’ (военное время), а также ‘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 считает месяц равным ровно 30 дням, а год — ровно 365,25 дням.
Не все удобные форматы являются строками. Если time — число (целое или с плавающей точкой), оно определяет относительное время, измеренное в секундах. Результат
encode-timeтакже может использоваться для указания абсолютного значения для time.В большинстве случаев repeat не влияет на то, когда происходит первый вызов — time сам по себе определяет это. Есть одно исключение: если time —
t, тогда таймер запускается всякий раз, когда время является кратным repeat секунд с момента эпохи. Это полезно для функций, таких какdisplay-time.Если 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, который ожидает ввода, а не с body, выполняющим длительное вычисление.
Функция 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-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Timers.html