我尝试读取行而不使用Async进行阻止。我已经弄清楚了如何阅读一行,但是我不知道使这一行连续的正确方法。理想情况下,我希望有一个生成器,可以在不阻塞主循环的情况下读取下一行。我该怎么办?
module Main where
import Control.Concurrent
import Control.Concurrent.Async
-- New async reader
main :: IO ()
main = do
getl <- async getLine
mainLoop getl
-- Read stdin and echo forever
mainLoop :: Async String -> IO ()
mainLoop getl = do
tryRead getl >>= tryPrint
threadDelay $ 1000 * 1000
mainLoop getl
-- Try to read stdin without blocking
tryRead :: Async String -> IO (Maybe String)
tryRead recvr = do
res <- poll recvr
case res of
Nothing -> return Nothing
Just (Right a) -> return $ Just a
Just (Left e) -> error $ show e
-- Try to print string
tryPrint :: Maybe String -> IO ()
tryPrint (Just str) = print str
tryPrint Nothing = return ()
输出。我假设发生的事情是,第一次对Async getline进行了评估,然后在每次轮询Async时都返回该值。
hell
"hell"
"hell"
"hell"
"hell"
"hell"
答案 0 :(得分:1)
使用unagi-chan的频道流的更好解决方案。
module Main where
import Control.Monad
import Control.Concurrent hiding (newChan, writeChan)
import Control.Concurrent.Chan.Unagi.NoBlocking
main :: IO ()
main = do
(inchan, outchan) <- newChan
_ <- forkIO $ getStdin inchan
[stream] <- streamChan 1 outchan
mainLoop stream
mainLoop :: Stream String -> IO ()
mainLoop stream = do
(str, stream') <- getNext stream
forM_ str print
threadDelay 1000
mainLoop stream'
getStdin :: InChan String -> IO ()
getStdin chan = forever $ getLine >>= writeChan chan
getNext :: Stream String -> IO (Maybe String, Stream String)
getNext stream = do
next <- tryReadNext stream
case next of
Next str stream' -> return (Just str, stream')
Pending -> return (Nothing, stream)
答案 1 :(得分:0)
虽然有些丑陋,但我还是一起破解了一些似乎可行的东西。 tryRead现在返回下一个要轮询的异步,它是旧的异步事件还是新的异步事件。 我想消除传递异步事件的必要性,但是我想现在就可以了。
module Main where
import Control.Concurrent
import Control.Concurrent.Async
-- New async reader
main :: IO ()
main = mainLoop Nothing
-- Read stdin and echo forever
mainLoop :: Maybe (Async String) -> IO ()
mainLoop getl = do
(res, getl') <- tryRead getl
tryPrint res
threadDelay 1000
mainLoop (Just getl')
-- Try to read stdin without blocking
tryRead :: Maybe (Async String) -> IO (Maybe String, Async String)
tryRead Nothing = do
recvr <- async getLine
return (Nothing, recvr)
tryRead (Just recvr) = do
res <- poll recvr
case res of
Nothing -> return (Nothing, recvr)
Just (Right a) -> do recvr' <- async getLine
return (Just a, recvr')
Just (Left e) -> error $ show e
-- Try to print string
tryPrint :: Maybe String -> IO ()
tryPrint (Just str) = print str
tryPrint Nothing = return ()