【问题标题】:How to kill the console input when process interrupted进程中断时如何终止控制台输入
【发布时间】:2015-06-05 19:18:10
【问题描述】:

我正在使用 Scalaz Stream 库并尝试创建一个简单的控制台应用程序。

我按照教程 scalaz streams 进行操作,他们有一个控制台读写示例。

但我遇到了一个奇怪的问题,我不确定如何解决。

这是我的代码:

import scala.concurrent.duration._
import scalaz.concurrent.Task

object StreamApp extends App {

  (new StreamExec).go3
}

class StreamExec {

  def gets: Task[String] = Task {
    scala.io.StdIn.readLine()
  }

  def puts(ln: String, answer: String): Task[Boolean] = Task {
    println(ln)
    ln.contains(answer)
  }

  def go3 {

    import scalaz.stream.Process

    val q = Seq("1", "2", "3") map { case p =>

      println(s"Say $p")

      val in = Process eval gets

      val out = in flatMap { line =>
        Process eval puts(line, p)
      }

      out.runLog.attemptRunFor(5.seconds)
    }

    println(q)
  }
}

当我运行它时,输出看起来像这样

background log: info: Say 1
1
background log: info: 1
background log: info: Say 2
background log: info: Say 3
3
3
background log: info: 3
background log: info: List(\/-(Vector(true)), -\/(java.util.concurrent.TimeoutException), \/-(Vector(true)))

1 很好,2 5 秒后超时失败,然后 3 需要输入两次。

问题在于,当进程按时失败时,控制台输入并未解除阻塞(未终止)并且仍在等待用户输入。

我尝试用 future 重现它,但遇到了同样的问题。

谢谢。

【问题讨论】:

    标签: scala functional-programming scalaz scalaz-stream


    【解决方案1】:

    通常在 scalaz 流中,您获取(获取值)然后处理它并终止。

    在此示例中,如果您的处理只是读取打印,则不需要 runLog,因此您想要的只是要处理的任意效果。

    我认为这段代码可能会有所帮助

    eval(gets)
    .flatMap { name =>   Process(1,2,3).flatMap( ln => eval(puts(ln,name))) }
    .take(3)
    .run.run
    

    你真正需要的是选择一个 Process1 组合子到pipe 你的进程,这最终会终止你的程序。 您可以尝试各种可用于构建程序的组合器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-02
      • 1970-01-01
      • 2014-05-18
      • 1970-01-01
      相关资源
      最近更新 更多