Celluloid

时间:2015-12-01 11:28:06

标签: ruby celluloid

在不阻塞actor的情况下生成子进程的最佳方法是什么?

我的目标是运行多个命令,完成后,获取输出和退出代码。 我尝试过这个,但显然,popen调用是阻塞的:

#!/usr/bin/env ruby

require 'celluloid/current'
require 'celluloid/io'

class MyProcessLauncher
    include Celluloid::IO

    def run
        every(1) { puts "tick" }

        every(5) {
            puts "Starting subprocess"
            ::IO.popen("sleep 10 && echo 'subprocess done'", :err=>[:child, :out]) { |io|
                puts io.read
            }
            puts $?.exitstatus
        }
    end
end

MyProcessLauncher.new.run
sleep

输出结果为:

tick
tick
tick
tick
Starting subprocess
subprocess done
0
tick
Starting subprocess

但我希望五个' tick'在每个' Starting subprocess' ...

之间

谢谢!

1 个答案:

答案 0 :(得分:2)

如果您想要返回值,则需要defer或使用future

defer(如果您不需要返回,则很容易)

every(5)区块中,要使用defer,请使用popen

打包defer {}来电(包括退出状态显示调用)

future(有点复杂)

有几种方法可以实现这种方法。我的建议是将every(5)的内容移动到它自己的方法,并在启动@futures时初始化数组MyProcessLauncher或类似...然后在every(5)内使用它拨打:

@futures = future.new_method

此外,添加一个新循环来处理您的未来。在every(5)添加一个新的处理程序(另一个every循环或async调用处理器方法(递归))来处理您的值之后,基本上这样做:

value = @futures.pop.value if @futures.any?
如果您遇到问题,我会询问有关期货的跟进问题,而且无法找到如何处理期货的例子。否则,您有两种方法可以无阻塞地处理popen次呼叫。