如果花费的时间超过X秒,则退出线程

时间:2011-06-25 22:39:56

标签: ruby-on-rails ruby multithreading ruby-on-rails-3

我正在使用这样的Ruby线程:

threads = []

for page in pages
  threads << Thread.new(page) { |myPage|

    h = Net::HTTP.new(myPage, 80)
    puts "Fetching: #{myPage}"
    resp, data = h.get('/', nil )
    puts "Got #{myPage}:  #{resp.message}"
  }
end

threads.each { |aThread|  aThread.join }

假设我想杀死一分钟后仍在运行的所有线程。我该怎么做?

2 个答案:

答案 0 :(得分:4)

我通常会使用Timeout暂停我的操作:

require "timeout"
Timeout.timeout(seconds) do
 ...
end

也许this可以提供帮助,所以在你的情况下,我认为这样的事情应该有效:

begin
  Timeout.timeout(5) do
    for page in pages
      threads << Thread.new(page) { |myPage|

        h = Net::HTTP.new(myPage, 80)
        puts "Fetching: #{myPage}"
        resp, data = h.get('/', nil )
        puts "Got #{myPage}:  #{resp.message}"
      }
    end
    threads.each { |aThread|  aThread.join }
  end
rescue Timeout::Error
   # kill threads here
end 

但你确定你的控制器是最好的地方吗?在背景任务中他们不会更好吗?

答案 1 :(得分:3)

我只是在构建h之后添加此行,而不是诉诸线程管理:

...
h = Net::HTTP.new(myPage, 80)
h.read_timeout = 60
...

这样,HTTP请求将在60秒后超时,线程将正常退出。

编辑:当然,您必须检查请求是否成功或是否超时。 ;)

进一步编辑:让我扩展您的代码:

threads = []

for page in pages
  threads << Thread.new(page) { |myPage|
    begin
      h = Net::HTTP.new(myPage, 80)
      h.read_timeout = 60
      puts "Fetching: #{myPage}"
      resp, data = h.get('/', nil )
      puts "Got #{myPage}:  #{resp.message}"
      # do something on a successful HTTP request.
    rescue TimeoutError => tErr
      # do something on an HTTP request that did timeout.
    end
  }
end

threads.each { |aThread|  aThread.join }