主线程外的ThreadDelay

时间:2014-06-29 15:27:16

标签: multithreading haskell concurrency

我一直在尝试编写一个函数,用字母逐字打印一个字符串,不带引号,并在每个字母之间暂停一点。例如,如果你给它“hello”,它将打印h,然后等待,e,然后等待,然后l,然后等待,然后l,然后等待,o。但是当我尝试使用threadDelay时,它会在主线程中暂停。所以它会暂停,然后一次打印所有内容。我试图在prints函数中分叉一个新线程,但它不起作用。救命!

import Control.Concurrent as C

clean :: String -> String
clean s@[c]               = s
clean ('"':s)  
    | last s == '"'       = init s
    | otherwise           = s
clean ('\'':s) 
    | last s == '\''      = init s           
    | otherwise           = s
clean s                   = s

prints :: String -> IO()
prints [] = putStrLn " "
prints (x:xs) = do
    C.forkIO $ do
        putStr $ clean (show x)
        C.threadDelay $ 10000
        prints xs  

main :: IO()
main = do 
    prints "hello"

1 个答案:

答案 0 :(得分:4)

您的代码存在一些问题。

首先,threadDelay微秒中接受一个参数,因此您添加的暂停太小而无法注意到。试试1000000

其次,除非您关闭stdout上的缓冲,否则IO库会缓冲您的输出,因此您将看不到预期的延迟。您可以使用System.IO控制此项:

import System.IO ( stdout, hSetBuffering, BufferMode(..) )

然后从hSetBuffering致电main

hSetBuffering stdout NoBuffering

最后,分离一个线程实际上是一个倒退,因为程序不会等待分叉的线程完成,所以只需删除它。如果你真的希望它在后台,你将需要使用MVar或类似的等待它完成,否则程序将自然地首先退出。