2015-06-05 4 views
2

Я играю в библиотеке 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 требует ввода в два раза ,

Проблема заключается в том, что при сбое процесса вовремя вход в консоль не разблокирован (не убит) и все еще ждет ввода пользователя.

Я попытался воспроизвести его с помощью фьючерсов и столкнулся с той же проблемой.

спасибо.

ответ

1

Обычно в потоке scalaz вы получаете (приобретаете значение), затем обрабатываете его и завершаете.

В этом примере, если ваша обработка только что прочитана, вам не нужно runLog, поэтому вы хотите просто обрабатывать произвольные эффекты.

Я думаю, что этот код может помочь

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

Что вам действительно нужно, чтобы выбрать один из комбинаторов process1 в pipe вашего процесса через и что в конечном итоге завершить свою программу. Вы можете поэкспериментировать с различными комбинаторами, доступными для создания вашей программы.