【问题标题】:Haskell, consume non-blocking getLineHaskell,使用非阻塞 getLine
【发布时间】:2020-09-15 18:36:30
【问题描述】:

我正在寻找一种从标准输入读取的方法,过了一会儿,如果没有输入,我想跳过那个 getLine。

我有这段代码在 3 秒后跳过第一个 getLine,但当它到达第二个 getLine 时,我必须输入两次。有什么建议吗?

main :: IO ()
main = do
  putStrLn "x:"
  x <- timeout 3000000 getLine
  putStrLn "y:"
  y <- getLine
  putStrLn y

【问题讨论】:

  • 所以你希望 getLine 无论如何都会发生,只有它的输出会在 3 秒后被忽略。一种方法是让一个辅助线程读取这些行,并将它们放入主线程提供的MVars 中。一种邪恶的方法是使用惰性 IO。
  • 无法重现。当我等待 3 秒后,输入 30,然后按 Enter,它会立即打印 30 并退出。
  • 好吧,我等 3 秒,输入 30,我必须再次输入 30 才能打印并退出。
  • 我也无法在 Linux 上重现,无论是通过 GHC 编译的可执行文件还是从“GHCi”运行。如果我等待“y:”提示出现的时间足够长(即大约 3 秒),我只需要输入 30 一次,程序就会回显它并退出。您在哪个平台上运行它,您是作为独立编译的可执行文件运行它还是在 GHCi 下运行它?
  • 我在Windows上测试过,使用ghc编译的exe。

标签: haskell io nonblocking


【解决方案1】:

不是一个完整的答案,但是...

我可以确认 Windows 上的行为。出现提示“x:”,3秒后出现提示“y:”,但忽略第一行输入。如果程序使用-threaded 编译,则在输入第一行之前不会出现“y:”提示。 (从某种意义上说,如果在超时后输入第一行,x 的值将是 Nothing,但无论哪种方式,只有第二行输入为 y &lt;- getLine 处理,所以超时仍然是“处理的”。 )

我认为根本问题可能是在 Windows 下通过异步异常中断 I/O 的问题,如 issue #7353 中所述。那里的错误报告听起来好像只有线程运行时受到影响,但我认为这是使用线程运行时还是非线程运行时的问题。 timeout 的实现具有用于处理 Windows 线程运行时的特殊代码路径,这可以解释行为上的差异,即使在这两种情况下运行时都未能取消第一个 getLine

本机 Windows I/O Manager 的工作正在进行中,它应该解决问题 #7353 以及 Windows 下 I/O 的许多其他问题。不过,我没有可以尝试在其上构建/测试它的 Windows 构建机器,以查看它是否解决了这个特定问题。

【讨论】:

    猜你喜欢
    • 2012-11-28
    • 2015-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-06
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    相关资源
    最近更新 更多