1

いくつかのスレッドを保持するクラスを作成し、タスクを実行し、最後にコールバック メソッドを呼び出すことが私の現在の目標であり、この道では特別なことは何もありません。

私の実験的なクラスは、特定の IP の特定のポートでいくつかの接続チェックを行い、ステータス情報を提供します。

だから私の試み:

check = ConnectionChecker.new do | threads |
   # i am done callback
end

check.check_connectivity(ip0, port0, timeout0, identifier0)
check.check_connectivity(ip1, port1, timeout1, identifier1)
check.check_connectivity(ip2, port2, timeout2, identifier2)

sleep while not check.is_done

最善のアプローチではないかもしれませんが、一般的には私の場合に適しています。

それで何が起こっているのですか:

私のクラスでは、コールバックを保存し、アクションを実行し、内部的なことを行います:

Thread.new-> 成功/失敗 -> すべて完了したら完了としてマーク -> コールバックを呼び出す:

 class ConnectionChecker

   attr_reader :is_done

   def initialize(&callback)
     @callback     = callback
     @thread_count = 0
     @threads      = []
     @is_done      = false
   end

   def check_connectivity(host, port, timeout, ident)
     @thread_count += 1
     @threads << Thread.new do

       status = false
       pid    = Process.spawn("nc -z #{host} #{port} >/dev/null")

       begin
         Timeout.timeout(timeout) do
           Process.wait(pid)
           status = true
         end
       rescue Process::TimeoutError => e
         Process.kill('TERM', pid)
       end

       mark_as_done
       #returnvalue for the callback.
       [status, ident]
     end
   end

   # one less to go..
   def mark_as_done
     @thread_count -= 1
     if @thread_count.zero?
       @is_done = true
       @callback.call(@threads)
     end
   end
 end

このコード - はい、開始メソッドがないことはわかっているので、すべてをすぐに呼び出すことを信頼する必要があります - 正常に動作します。

しかし、これらの2行を交換すると:

  @is_done = true
  @callback.call(@threads)

  @callback.call(@threads)
  @is_done = true

それから最後の行、

sleep while not check.is_done

無限ループになる。デバッグすると、コールバックが適切に呼び出されていることがわかります。 の値を確認すると、is_done実際には常に ですfalse。クロージャーに入れていないので、なぜこれが起こっているのだろうか。

コールバック自体も空のis_doneままにすることができますfalse(そのため、誤ってキャッチされた例外はありません)。

この場合、最後のスレッドのステータスが実行中であることに気付きました。私はスレッドの値を尋ねなかったので、ここでこつがわかりません。

この問題に関するドキュメント/情報はありますか? また、それの名前は問題ありません。

4

1 に答える 1

1

スレッドの安全性を確保するために Mutex を使用してみてください :)

于 2012-08-07T12:27:48.367 に答える