等待Haskell中的两个输入,同时

时间:2010-01-11 06:23:40

标签: haskell concurrency io

标题可能有点模糊。这就是我的意思:

说我有两种获取输入方式的方法。第一种是通过键盘,使用函数getLine阻塞直到读取一行。另一个是,例如,通过TChan,其中使用readTChan chan也将导致一个块,直到通道中存在一个值,然后它将被读取。

我想要完成的是能够等待两个值,使用单个线程并且不允许我的CPU跳转到100%。当两个值中的一个可用时,将获取它并重新启动程序。 (假设,使用Either通知收到了两个值中的哪一个。)

这可能吗?

非常感谢!

3 个答案:

答案 0 :(得分:12)

我不认为“使用单个线程”在这里有意义。您必须已经使用多个Haskell线程来写入TChan。您应该使用两个Haskell线程来执行此操作,并使用MVar或类似来传达第一个结果到达。例如:

module Main where

import System.IO
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Concurrent.STM
import Control.Concurrent.STM.TChan

main = do
   chan <- newTChanIO
   forkIO (threadTChanWrite chan)
   threadMultiplexedRead chan

threadTChanWrite chan = do
   threadDelay 5000000
   atomically $ writeTChan chan 3

threadMultiplexedRead chan = do
   mvar <- newEmptyMVar
   forkIO (threadKeyboardRead mvar)
   forkIO (threadTChanRead mvar chan)
   v <- readMVar mvar
   print v

threadKeyboardRead mvar = do
   str <- getLine
   putMVar mvar (Right str)

threadTChanRead mvar chan = do
   v <- atomically (readTChan chan)
   putMVar mvar (Left v)

一个正确的实现可能会清理之后留下的线程,顺便说一句。

答案 1 :(得分:5)

  

我有两种获取输入程序的方法

你应该能够使用2个线程,每个输入源一个,等待各自的输入,将结果写入共享通道或mvar由第三个线程控制。

答案 2 :(得分:2)

hackage上的“async”包中有playerView.loadVideoWithId(videoId: "jCHE0Tjw6MA", playerVars: playerVars) 辅助函数。

同时运行两个IO操作,因此一个可能是race :: IO a -> IO b -> IO (Either a b),另一个可能是getLine或其他阻止。返回MVar,指示哪一个首先返回(另一个被取消)。

https://hackage.haskell.org/package/async-2.0.2/docs/Control-Concurrent-Async.html#v:race