【问题标题】:ruby has nothing like a Fiber.kill?ruby 没有像 Fiber.kill 这样的东西?
【发布时间】:2023-03-06 08:33:01
【问题描述】:

我正在使用 Fibers 来处理不同代码块之间的调度,事实证明这比尝试管理线程要简单得多,因为我的用例相当简单(并且一次只涉及运行一个脚本)。不幸的是,我需要偶尔“杀死” Fiber 的能力,但 Fiber 中似乎没有任何东西类似于 Thread.kill

我的 Fibers 只是运行一个用户提供的模板,所以如果输入大量“我被杀了吗?如果是,我需要一直返回到顶层”会过于笨拙。而且 Fiber 中的“exit”也只是在整个 ruby​​ 解释器上调用 exit。

有什么方法可以杀死光纤或让光纤完全“退出”它的工作?

失败了(也许这是另一个问题,但它说明了我为什么要寻找 Fiber.kill) - 我也在研究使用 Threads 基本上实现 Fibers(具有额外的“杀死”能力),但是我看不到有任何方法可以执行 thr.run 或 thr.join,它会等到线程到达 Thread.stop,然后允许我在我的主调度程序中再次控制,所以线程似乎没有也能够解决我的情况 - 没有一个主线程,它只是启动一个线程并坐下来轮询线程以完成它的工作部分,这看起来充其量是混乱和麻烦的。

【问题讨论】:

  • 纤维可能不是您想要做的事情的正确方法。光纤不是由解释器安排的或被抢占的;因为它们是自我管理的,所以退出的方式是让步或让区块完成。
  • 我实际上并不想要由解释器安排或抢占的东西。在各方面,Fibers 都非常适合我想要的,除了它们没有办法被终止。
  • 这就是光纤的本质——因为它们自己管理,所以没有办法在外部终止它们。你必须有办法让光纤检测到它应该结束并离开块。

标签: ruby kill fibers


【解决方案1】:

我很难理解 yield/resume 是如何解决您的问题的 - 但是当光纤已经屈服时,您可以使用 raise Fiber#raise 中止它


def build_fibre
  Fiber.new do |first|
    puts 'doing work'
    3.times { Fiber.yield false }

    puts 'finished work'
    true
  rescue
    puts 'aborted'
  end
end


fiber1 = build_fibre
fiber1.resume

# Raise an exception at the `yield` call
fiber1.raise

fiber2 = build_fibre
loop do
  puts 'waiting'
  break if fiber2.resume
end

puts 'finished'

【讨论】:

  • 请注意,Fiber#raise 是在 v2.7 中添加的,不适用于旧版本。
  • 太棒了 - 我没有考虑向 Fiber 发送异常来杀死它。这解决了我的问题。我不能使用yield/resume,因为所有的纤程管理都是由库调用处理的,并且这些调用能够终止纤程 - 所以他们需要一种能够完全退出纤程但从调用内部退出的方法.. 所以捕捉一个特定的异常就是答案。
猜你喜欢
  • 2011-05-03
  • 2013-07-30
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多