創建一個包含一些線程,執行任務並最終調用回調方法的類是我當前的目標,在這條道路上沒有什麼特別的。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