处理在Ruby线程中引发的异常 [英] Handling exceptions raised in a Ruby thread

查看:106
本文介绍了处理在Ruby线程中引发的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一个经典的异常处理问题的解决方案。考虑以下代码:

  def foo(n)
putsfor#{n}$ b $


开始
线程= []
[5,15,20,3] |我| |
线程<< Thread.new do
foo(i)
end
end

threads.each(&:join)
rescue Exception => e
放EXCEPTION:#{e.inspect}
putsMESSAGE:#{e.message}
end

此代码在5秒钟后捕获异常。



但是,如果将数组更改为 [15,5,20,3] ,上面的代码在15秒后捕获异常。总之,它总是捕获第一个线程中引发的异常。



任何想法,为什么这样。为什么每次3秒钟后都不能捕获异常?如何捕获任何线程的第一个引发的异常?

解决方案

如果您希望任何线程中的任何未处理的异常导致解释器要退出,您需要设置主题:: abort_on_exception = true 。未处理的异常导致线程停止运行。如果您不将此变量设置为true,则只会在调用 Thread#join Thread#value 为线程。如果设置为true,它将在它发生时被提升,并将传播到主线程。

  Thread.abort_on_exception = true#add 

def foo(n)
放入for#{n}
sleep n
raiseafter#{n}
end

begin
threads = []
[15,5,20,3] .each do | i |
线程<< Thread.new do
foo(i)
end
end
threads.each(&:join)

rescue Exception => e

放EXCEPTION:#{e.inspect}
putsMESSAGE:#{e.message}
end

输出:

  5 
为20
为3
为15
EXCEPTION:#< RuntimeError:after 3>
MESSAGE:after 3

注意:但是如果您希望任何特定的线程实例引发异常这样就有类似的 abort_on_exception =线程实例方法

  t = Thread.new {
#执行某些操作并引发异常
}
t.abort_on_exception =真


I am looking for a solution of classic problem of exception handling. Consider following piece of code:

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

This code catches the exception after 5 seconds.

But if I change the array as [15, 5, 20, 3], above code catch the exception after 15 seconds. In short, it always catch the exception raised in first thread.

Any idea, why so. Why doesn't it catch the exception after 3 seconds each time? How do I catch the first raised exception by any thread?

解决方案

If you want any unhandled exception in any thread to cause the interpreter to exit, you need to set Thread::abort_on_exception= to true. Unhandled exception cause the thread to stop running. If you don't set this variable to true, exception will only be raised when you call Thread#join or Thread#value for the thread. If set to true it will be raised when it occurs and will propagate to the main thread.

Thread.abort_on_exception=true # add this

def foo(n)
    puts " for #{n}"
    sleep n
    raise "after #{n}"
end

begin
    threads = []
    [15, 5, 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

Output:

 for 5
 for 20
 for 3
 for 15
EXCEPTION: #<RuntimeError: after 3>
MESSAGE: after 3

Note: but if you want any particular thread instance to raise exception this way there are similar abort_on_exception= Thread instance method:

t = Thread.new {
   # do something and raise exception
}
t.abort_on_exception = true

这篇关于处理在Ruby线程中引发的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆