【问题标题】:Ruby threads: how to catch an exception without calling .join?Ruby 线程:如何在不调用 .join 的情况下捕获异常?
【发布时间】:2014-11-11 21:14:44
【问题描述】:

如何在不使用.join的情况下观察和挽救线程中发生的错误?我现在拥有的代码:

Thread.abort_on_exception = true
begin
    a = Thread.new { errory_code }
rescue Exception => detail
    puts detail.message
end

sleep 1 #so that thread has enough time to execute 

如果我理解正确,Thread.abort_on_exception = true 会中止线程执行(即引发异常)。但是为什么救援没有抓住它呢?

【问题讨论】:

    标签: ruby multithreading


    【解决方案1】:

    您希望 rescue 操作能够从 Ruby 退出 begin ... end 块后运行很长时间的一段代码中捕获异常。这不会发生。

    请记住,当您处理线程时,事情会发生混乱。

    您可以捕获的唯一异常是与线程创建有关的异常。线程内部发生的事情完全是另一个世界。

    使用join 会强制您的代码等待线程完成,这样才能正确排序。然后可以捕获线程异常。

    【讨论】:

    • 嗯。那么还有其他的订购方式吗? (我不能使用.join,因为许多连接需要位于不同的位置——这将导致它们相互等待完成)。我可以在不同的地方有两个单独的线程并在其中捕获异常并知道异常发生在哪个线程中吗?
    • 线程不会等待,但你的外线程管理代码会。如果您需要在继续之前完成所有操作,那么在他们已经完成的每个工具上调用 join 并没有什么坏处。无论顺序如何,它都会等待运行时间最长的那个完成。
    • 在这种情况下:a = Thread.new { 5.times { |i| p i; sleep 0.3 } }; a.join; b = Thread.new { 5.times { |k| p k } }; b.join; b 线程将等待一个线程完成后才悲伤地开始。
    • 任何一点你都有一个join,它将停止执行直到子线程完成。而是在最后做a.join; b.join。一般规则:在需要时不要等待线程。
    【解决方案2】:

    我想出了办法——我只需要将我的线程内部包装成这样的救援块:

    Thread.abort_on_exception = true
    
    a = Thread.new do 
        begin                      #new
            errory_code 
        rescue Exception => detail #new
            puts detail.message    #new
        end                        #new
    end
    
    sleep 1 #so that thread has enough time to execute 
    

    这是一个非常明显的解决方案, - 但是,由于我花了这么长时间才想到它,希望能对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2011-05-01
      • 2022-07-29
      • 2021-05-25
      • 2011-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      相关资源
      最近更新 更多