这是我的Traveller项目中的一个子问题。
我已经将处理输入的基本代码组合在一起。它是有效的,直到我将一个TChan引入到混搭中。下面是工作代码,以及如何使用它的示例。然后,我将更改它并解释我为什么要这样做。然后,我将讨论这个问题。
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad (forever)
import Control.Concurrent (forkIO)
import Control.Monad.STM (STM,atomically)
import Control.Concurrent.STM.TChan
import Reactive.Banana
import Reactive.Banana.Frameworks
data Planet = Vulcan
| Mars
| Terra
deriving (Eq,Read,Show)
data Command = Move Planet
| Look
| Quit
| Null
deriving Show
makeNetworkDescription :: AddHandler (Maybe Command) -> IO EventNetwork
makeNetworkDescription addCommandEvent = compile $ do
eInput <- fromAddHandler addCommandEvent
let eCommand = filterJust eInput
bCommand = stepper Null eCommand
eCommandChanged <- changes bCommand
reactimate $ (\n -> appendFile "output.txt" ("Command is " ++ show n)) <$>
eCommandChanged在ghci中执行以下命令将证明这是可行的。
(addCommandEvent,fireCommand) <- newAddHandler :: IO (AddHandler (Maybe Command),Maybe Command -> IO ())
networkDescr <- makeNetworkDescription addCommandEvent
actuate networkDescr
return (Just $ Look) >>= fireCommand所以,现在我已经有了基本的机制,我想开始构建它。这将是一个多人游戏。解决这个问题的第一步就是从TChan获取输入。这个想法是,所有的玩家都将写入这个TChan,并且每个命令都将按照它到达的顺序进行处理。
所以我添加了一个新函数'inputFrame‘
inputFrame :: TChan Command -> IO ()
inputFrame commandChannel = do
(addCommandEvent,fireCommand) <- newAddHandler
networkDescr <- makeNetworkDescription addCommandEvent
actuate networkDescr
forkIO $ forever (atomically $ tryReadTChan commandChannel) >>= fireCommand
return ()下面是我在ghci中尝试使用它的方法。
commandChan <- atomically $ newTChan :: IO (TChan Command)
_ <- atomically $ writeTChan commandChan Lookoutput.txt不会被写入。commandChan正在被读取,因为我检查它在填充后是否为空。我做错了什么是显而易见的吗?如果不是,我该如何解决这个问题?另外,对于我的预期目的,TChan是正确的选择吗?
发布于 2012-10-17 01:52:06
你可能想要
forkIO $ forever (atomically (tryReadTChan commandChannel) >>= fireCommand)但是我还没有测试过这个。此外,在这里,您可能会想要避免使用tryReadTChan。只需使用普通的老式readTChan,这样您就可以获得有效的retry,而不是轮询。
https://stackoverflow.com/questions/12919136
复制相似问题