我正在寻找异常处理的经典问题的解决方案。考虑以下代码:
def foo(n)
puts " for #{n}"
sleep n
raise "after #{n}"
end
begin
threads = []
[5, 15, 20, 3].each do |i|
threads << Thread.new do
foo(i)
end
end
threads.each(&:join)
rescue Exception => e
puts "EXCEPTION: #{e.inspect}"
puts "MESSAGE: #{e.message}"
end
字符串
此代码在5秒后捕获异常。
但是如果我将数组改为[15, 5, 20, 3]
,上面的代码会在15秒后捕获异常。简而言之,它总是捕获第一个线程引发的异常。
有什么想法吗,为什么会这样。为什么每次都不是在3秒后捕获异常?我如何捕获任何线程的第一个异常?
5条答案
按热度按时间oiopk7p51#
如果你想让任何线程中的任何未处理的异常导致解释器退出,你需要将Thread::abort_on_exception=设置为
true
。未处理的异常会导致线程停止运行。如果你不将这个变量设置为true,异常只会在你为线程调用Thread#join
或Thread#value
时引发。如果设置为true,它会在发生时引发,并传播到主线程。字符串
输出量:
型
注意:但是如果你想让任何特定的线程示例以这种方式引发异常,有类似的abort_on_exception= Thread示例方法:
型
vq8itlhq2#
字符串
fumotvh33#
延迟异常处理(灵感来自@Jason Ling)
字符串
huus2vyu4#
这将等待第一个线程提升或返回(并重新提升):
字符串
gmol16395#
Jason Ling的回答会遗漏传递给Thread.new的任何参数。这会破坏Puma和其他宝石。为了避免这个问题,你可以用途:
字符串