在Emacs Lisp中的sleep函数

21

脚本 A

    (insert (current-time-string))
    (sleep-for 5)
    (insert (current-time-string))

M-x eval-buffer,插入两个相隔5秒的时间字符串

脚本B

一些comint代码(添加钩子并启动进程)

    (sleep-for 60) ;delay a bit for process to finish
    (insert "ZZZ")

我使用M-x eval-buffer时,"ZZZ"立即被插入了,没有任何延迟。

可能发生了什么?顺便说一下,我在Win XP上使用的是Emacs 23.2。


我也遇到过这种情况。在批处理模式下,sleep-for 有时会被忽略。 - Gracjan Polak
3个回答

12
如果你只是想等待一个进程完成,那么你可能根本不需要使用sleep-for。相反,应该同步地调用进程,而不是异步地调用它:

http://www.gnu.org/software/emacs/manual/html_node/elisp/Synchronous-Processes.html#Synchronous-Processes

这样,Emacs会一直阻塞,直到进程完成。
如果你必须(或者真的想要)使用异步进程,例如因为它需要很长时间而你不希望Emacs在此期间冻结(你说了60秒,这相当长),那么等待进程完成的正确方法是使用sentinel。Sentinel是一个回调函数,每当进程状态发生变化时调用,例如,当进程终止时。
(defun my-start-process ()
  "Returns a process object of an asynchronous process."
  ...)

(defun my-on-status-change (process status)
  "Callback that receives notice for every change of the `status' of `process'."
  (cond ((string= status "finished\n") (insert "ZZZ"))
        (t (do-something-else))))

;; run process with callback
(let ((process (my-start-process)))
  (when process
    (set-process-sentinel process 'my-on-status-change)))

1
示例代码和链接都很棒,我尝试了同步处理,对我来说效果很好,虽然60秒的等待有点长。非常感谢,Thomas。 - Bill Rong

12

它可能会打断睡眠以处理子进程IO。 对于这种“稍稍延迟进程”的操作,应该真正使用像run-with-idle-timer这样的东西,因为Emacs是单线程的。


我不知道Emacs是单线程的。感谢您的快速回复。我了解了run-with-idle-timer,并认为可能应该从一开始就使用同步进程。 - Bill Rong

2
官方文档可以看出,它可能不仅仅由'sleep-for而且也由'sit-for实现:
(defun smart-translate ()
  "Shows translation of a word at the current point
at the full frame for several seconds and 
returns to the initial buffer"
  (interactive)
  (google-translate-at-point)
  (switch-to-buffer "*Google Translate*")
  (delete-other-windows)
  (sit-for 5)
  (previous-buffer)
  )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接