创建一个包含一些线程,执行任务并最终调用回调方法的类是我当前的目标,在这条道路上没有什么特别的。Ruby线程回调奇怪的行为
我的实验类对给定IP的特定端口进行一些连接检查,给我一个状态信息。
所以我尝试:
check = ConnectionChecker.new do | threads |
# i am done callback
end
check.check_connectivity(ip0, port0, timeout0, identifier0)
check.check_connectivity(ip1, port1, timeout1, identifier1)
check.check_connectivity(ip2, port2, timeout2, identifier2)
sleep while not check.is_done
也许不是最好的方法,但一般它适合我的情况。
所以发生了什么:
在我的课我存储的回调,执行的操作,做内部的东西:
Thread.new
- >成功/失败 - >标记为已完成,当全部完成 - >调用回调:
class ConnectionChecker
attr_reader :is_done
def initialize(&callback)
@callback = callback
@thread_count = 0
@threads = []
@is_done = false
end
def check_connectivity(host, port, timeout, ident)
@thread_count += 1
@threads << Thread.new do
status = false
pid = Process.spawn("nc -z #{host} #{port} >/dev/null")
begin
Timeout.timeout(timeout) do
Process.wait(pid)
status = true
end
rescue Process::TimeoutError => e
Process.kill('TERM', pid)
end
mark_as_done
#returnvalue for the callback.
[status, ident]
end
end
# one less to go..
def mark_as_done
@thread_count -= 1
if @thread_count.zero?
@is_done = true
@callback.call(@threads)
end
end
end
此代码 - 是的,我知道有没有启动方法,所以我必须相信,我立即称它 - 工作正常。
但是,当我换这两条线:
@is_done = true
@callback.call(@threads)
到
@callback.call(@threads)
@is_done = true
然后最后一行,
sleep while not check.is_done
成为一个无限循环。调试显示我的回调调用正确,当我检查is_done
的值时,它确实总是false
。由于我没有把它放到一个闭包中,我想知道为什么会发生这种情况。
回调本身也可以是空的,is_done
仍然是false
(所以没有误捕的例外)。
在这种情况下,我注意到最后一个线程处于状态运行状态。由于我没有要求线程的价值,我只是没有得到挂在这里。
有关此问题的任何文档/信息?另外,它的名字会很好。
如果不使用互斥锁,则无法预测线程行为。考虑不同的ruby实现。 – pguardiario 2012-08-07 11:49:02
@pguardiario啊完美,非常感谢。现在它按照我想要的顺序工作。如果你想要点,把它作为答案;) – thedanielhanke 2012-08-07 12:04:25