如何在Ruby中对循环进行延迟?

17
例如,如果我想制作一个计时器,在循环中如何延迟以使其按秒计数而不仅仅是在毫秒级别上循环?

你可以在循环中使用 sleep 1 命令来让程序休眠一秒钟。http://www.ruby-doc.org/core-2.2.0/Kernel.html#method-i-sleep - Michael Berkowski
2
"[5,4,3,2,1].each {|n| puts n; sleep 1}"会每秒倒数一次从5到1,例如。这是您要找的吗? - Michael Berkowski
是的,看起来很棒!但是是否可以输入一个数字(比如14),然后按照相同的方式计数到指定的数字? - Salviati
@ZippO 所以你是在问如何在Ruby中制作一个计数器?将Phrogz的上面片段用def/end包裹起来,形成一个函数def counter(n),并将5替换为n - Michael Berkowski
嗯,我问的原因是因为我想要一个倒计时器,就像你写的第一段代码一样,只是想了解其他实现方式。好的,谢谢!我会试一下的! - Salviati
显示剩余3条评论
2个回答

33

在你提出非常简单的直接问题后,上面的“评论”就是你的答案:

1.upto(5) do |n|
  puts n
  sleep 1 # second
end

如果你想要定期运行一个方法,而不阻塞代码的其余部分,那么你需要使用线程(并可能创建互斥锁来确保两个代码片段不会同时修改同一个数据结构):

require 'thread'

items = []
one_at_a_time = Mutex.new

# Show the values every 5 seconds
Thread.new do
  loop do
    one_at_a_time.synchronize do
      puts "Items are now: #{items.inspect}"
      sleep 5
    end
  end
end

1000.times do
  one_at_a_time.synchronize do
    new_items = fetch_items_from_web
    a.concat( new_items )
  end
end

14
一些人认为将一个常数时间间隔作为参数传递给sleep方法就可以实现预期效果。然而,请注意没有任何方法需要零时间。如果在循环中放置sleep(1),只要循环中还有其他内容,循环的周期肯定会超过1秒。更糟糕的是,处理循环的每次迭代所需的时间并不总是相同的。每个循环周期都需要超过1秒,并且误差是随机的。当循环不断运行时,这种误差会不断蔓延并向正方向增长。特别是如果您想要一个计时器,在这种情况下周期很重要,那么您不应该这样做。
使用指定常数时间间隔的正确循环方式如下:
loop do
  t = Time.now
    #... content of the loop
  sleep(t + 1 - Time.now)
end

产生错误:TypeError:无法将时间转换为时间间隔。 - user1724295
如果循环的内容需要超过一秒钟或者其他指定的时间,你将会收到这个错误提示:ArgumentError: time interval must not be negative - Fatima

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