5

我正在尝试使用 ruby​​ 编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是 Ruby 似乎无法在线程中捕获错误,这是一个示例:

#! /usr/bin/ruby

Thread.new {
  loop {
    $stdout.puts "hi"
    abc.puts ef
    sleep 1
  }
}


loop {
  sleep 1
}

显然,如果我在线程之外键入abc.puts ef代码,将永远不会运行,因为 Ruby 会报告“未定义的变量 abc”。但是,如果它在线程内,则没有错误报告。我的问题是,如何让 Ruby 捕获这样的错误?或者至少,报告某个线程中有问题?

4

3 回答 3

6

使用Thread::abort_on_exception=

根据线程 - 异常处理

任何线程都可以使用 raise 实例方法引发异常,该方法的操作类似于 Kernel#raise。

但是,需要注意的是,除主线程外的任何线程中发生的异常都取决于 abort_on_exception。此选项默认为 false,这意味着任何未处理的异常都将导致线程在被连接或值等待时静默终止。您可以通过 abort_on_exception= true 或将 $DEBUG 设置为 true 来更改此默认值。

...

Thread::abort_on_exception = true
Thread.new {
  loop {
    $stdout.puts "hi"
    abc.puts ef
    sleep 1
  }
}


loop {
  sleep 1
}

=>

hi
t.rb:5:in `block (2 levels) in <main>': undefined local variable or method `abc' for main:Object (NameError)
        from t.rb:3:in `loop'
        from t.rb:3:in `block in <main>'
于 2013-08-17T18:40:51.017 回答
3

对于语法错误捕获,rescue 必须使用显式异常类(没有这个,rescue catch only StandardError):

Thread.new {  
begin
  abc.puts ef
rescue  Exception => e
  puts "error #{e}"
end
}

请参阅为什么默认情况下 `rescue` 不能捕获 `StandardError` 以外的异常类?

于 2013-08-17T19:19:07.810 回答
0

好的,一种可能的解决方案是用块包围线程 lambda begin rescue end

Thread.new {
begin
  abc.puts ef
rescue
  puts error
end
}
于 2013-08-17T18:37:48.090 回答