5

ruby を使用して 2 スレッド クライアントをコーディングしようとしています。1 つのスレッドがソケットからデータを読み取って出力し、もう 1 つのスレッドがローカル データを読み取ってリモート サーバーに送信します。私が見つけた問題は、Ruby がスレッド内のエラーをキャプチャできないように見えることです。以下に例を示します。

#! /usr/bin/ruby

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


loop {
  sleep 1
}

明らかに、abc.puts efRuby が「未定義の変数 abc」を報告するため、コードを入力してもスレッドの外では実行されません。ただし、スレッド内にある場合、エラー レポートはありません。私の質問は、Ruby にこのようなエラーをキャプチャさせる方法は? または、少なくとも、スレッド内で何か問題があることを報告しますか?

4

3 に答える 3

6

Thread::abort_on_exception=を使用します。

Thread - Exception Handlingによると:

Kernel#raise と同様に動作する 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

構文エラーをキャッチするには、レスキューは明示的な例外クラスを使用する必要があります (これがないと、レスキューは StandardError のみをキャッチします) :

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

デフォルトで `rescue` が `StandardError` 以外の例外クラスをキャッチできないのはなぜですか? を参照してください。

于 2013-08-17T19:19:07.810 に答える
0

begin rescue endOK、考えられる解決策の 1 つは、スレッド ラムダをブロックで囲むことです。

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