Scala - 在外部进程退出时获得回调

dvm*_*lls 10 scala

我想用scala替换我的很多perl.我倾向于做的很多事情之一就是调用二进制文件(通常是编译的C++,但可能是java,其他perl脚本,q脚本等),由我公司的其他团队提供给我.

例如,要做一些复杂的数学运算,我会启动一个外部二进制文件,然后将输入管道输入它.然后,我会收听其stdout流的结果,并stderr流式传输诊断消息.在perl中,我会使用POE::Wheel::Run小部件来完成此操作.我在scala中提出了类似(并且更好)的东西,但我想让它更强大.这是一个围绕ProcessIO物体的小包装.它看起来像这样:

class Exe(command: String, out: String => Unit, err: String => Unit) {

    import scala.sys.process._
    import scala.io._
    import java.io._
    import scala.concurrent._

    val inputStream = new SyncVar[OutputStream];

    val process = Process(command).run(
        new ProcessIO(
            stdin => inputStream.put(stdin),
            stdout => Source.fromInputStream(stdout).getLines.foreach(out),
            stderr => Source.fromInputStream(stderr).getLines.foreach(err)));

    def write(s: String): Unit = synchronized {
        inputStream.get.write((s + "\n").getBytes)
    }

    def close(): Unit = {
        inputStream.get.close
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我会像这样使用它:

val exe = new Exe("tr [a-z] [A-Z]", 
                  out => println("o: " + out), 
                  err => println("e: " + err))
exe.write("lower")
exe.close()
Run Code Online (Sandbox Code Playgroud)

打印出来:

o: LOWER
Run Code Online (Sandbox Code Playgroud)

这让我获得90%,但是当进程退出时,最好是获得回调.它可能会退出,因为我已关闭输入流并且其内部循环停止,它可能会自行退出,或者它可能会退出,因为我已将其杀死.在回调中,最好知道它停止的原因和退出代码.

我对如何解决这个问题感到有点失落,任何帮助都会受到赞赏(对上述代码的任何编辑当然都是受欢迎的 - 我有点像菜鸟).

我正在使用2.9.0.1

Did*_*ont 10

您可以等待进程调用结束exitValue.您可以在单独的线程中执行此操作,其中将发生回调.也许上课Process可能是拉皮条的:

import scala.concurrent.ops.spawn
implicit def ProcessWithCallback(p: Process) {
  def whenTerminatedDo(callback: Int => Unit) = spawn{
    val exitValue = p.exitValue; callback(p)
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以随意使用它Exe.

Process由JVM提供并包含的类scala.sys.Process非常可行,很难不阻塞线程

  • 没有单独的线程阻塞或轮询就无法获得回调(无论提供什么支持`进程`).也就是说,民意调查本来不错. (2认同)