对于这个答案,我编写了如下代码:
def show_wait_spinner
dirty = false
spinner = Thread.new{
loop{
print "*"
dirty = true
sleep 0.1
print "\b"
dirty = false
}
}
yield
spinner.kill
print "\b" if dirty
end
print "A"
show_wait_spinner{ sleep rand }
puts "B"
目标是确保最终输出是"AB"
-"\b"
如果线程尚未打印最终结果,则打印它。在存在的 Ruby 中,该代码对我来说似乎很乱begin/rescue/ensure
。所以我尝试了一些其他的实现show_wait_spinner
;他们都无法确保"AB"
始终是输出,并且永远不会"A*B"
or "AB*"
。
有没有更干净、更 Ruby 风格的方式来实现这个逻辑?
通过 Mutex 在循环结束时停止
def show_wait_spinner
stop = false
stopm = Mutex.new
spinner = Thread.new{
loop{
print "*"
sleep 0.1
print "\b"
stopm.synchronize{ break if stop }
}
}
yield
stopm.synchronize{ stop = true }
STDOUT.flush
end
......但我的逻辑必须是关闭的,因为这总是导致“A * B”。
通过线程局部变量在循环结束时停止
第二次尝试导致有时打印“A*B”,有时打印“AB”:
def show_wait_spinner
stop = false
spinner = Thread.new{
Thread.current[:stop] = false
loop{
print "*"
sleep 0.1
print "\b"
stopm.synchronize{ break if Thread.current[:stop] }
}
}
yield
spinner[:stop] = true
STDOUT.flush
end
杀死并确保线程
def show_wait_spinner
spinner = Thread.new{
dirty = false
begin
loop{
print "*"
dirty = true
sleep 0.1
print "\b"
dirty = false
}
ensure
print "\b" if dirty
end
}
yield
spinner.kill
STDOUT.flush
end
提高和拯救线程
def show_wait_spinner
spinner = Thread.new{
dirty = false
begin
loop{
print "*"
dirty = true
sleep 0.1
print "\b"
dirty = false
}
rescue
puts "YAY"
print "\b" if dirty
end
}
yield
spinner.raise
STDOUT.flush
end