我试图制作一个打印箭头的程序,直到用户按下回车键(参见下面的代码)。
问题是,当我按下回车键时,我会看到"停止"控制台中的字符串,但它不会在outputArrows函数中更改m的值。
我如何分享州?
import Control.Concurrent
import Control.Concurrent.Async
import Control.Monad
waitForInput m = do
getLine
putStrLn "stop"
putMVar m True
outputArrows m = do
stop <- readMVar m
unless stop $ do
threadDelay 1000000
putStr ">"
outputArrows m
main = do
m <- newMVar False
th1 <- async (waitForInput m)
th2 <- async (outputArrows m)
wait th1
wait th2
答案 0 :(得分:7)
您的putMVar
实际上并没有在MVar
中添加新值,而是无限期阻止。 MVar就像只能容纳一个值的盒子。如果要替换该值,则需要先取出旧值。
答案 1 :(得分:3)
您应该使用swapMVar
代替putMVar
。正如@shang所提到的那样,putMVar
会阻塞,直到MVar
为空,因此putMVar
永远不会完成:
waitForInput m = do
getLine
putStrLn "stop"
swapMVar m True
或者,您可以使用空MVar ()
作为布尔标志:
waitForInput :: MVar () -> IO ()
waitForInput m = do
getLine
putStrLn "stop"
putMVar m ()
outputArrows :: MVar () -> IO ()
outputArrows m = do
running <- isEmptyMVar m
when running $ do
threadDelay 1000000
putStr ">"
outputArrows m
main :: IO ()
main = do
hSetBuffering stdout NoBuffering
m <- newEmptyMVar
th1 <- async (waitForInput m)
th2 <- async (outputArrows m)
wait th1
wait th2