下面是一個示例程序的源:unsafePerformIO在線程應用程序無法正常工作
當我從ghci中運行它都PRINTJOB和printJob2運行正常,寫十行到一個文本文件中。
但是,當使用-threaded標誌編譯時,程序只寫入一行。
我有ArchLinux的
以下是編譯命令GHC 7.0.3:
ghc -threaded -Wall -O2 -rtsopts -with-rtsopts=-N -o testmvar testmvar.hs
什麼我做錯了嗎?爲什麼它不能在線程模式下工作?
import Control.Concurrent.MVar
import Control.Concurrent (forkIO)
import Control.Exception (bracket)
import Control.Monad (forM_)
import System.IO.Unsafe (unsafePerformIO)
import System.IO (hPutStrLn, stderr)
{-# NOINLINE p #-}
p :: MVar Int
p = unsafePerformIO $ newMVar (1::Int)
{-# NOINLINE printJob #-}
printJob x = bracket (takeMVar p) (putMVar p . (+ 1))
(\a -> do
appendFile "mvarlog.txt" $ "Input: " ++ x ++ "; Counter: " ++ show a ++ "\n"
)
{-# NOINLINE printJob2 #-}
printJob2 = unsafePerformIO $ do
p2 <- newEmptyMVar
return $ (\x -> bracket (putMVar p2 True) (\_ -> takeMVar p2)
(\_ -> do
appendFile "mvarlog.txt" $ "preformed " ++ x ++ "\n"
))
main = do
forM_ [1..10]
(\x -> forkIO $ printJob (show x))
編輯:哈馬爾指出,如果主應用程序退出早於所有產生的線程,那麼他們將被殺死,並建議在主末尾添加的延遲。 我的確如他預測的那樣工作。
我不確定這裏發生了什麼(編譯可能會觸發GHCi不存在的優化,並且這些優化消除了對'unsafePerformIO'的調用),但是我覺得值得再次說'顧名思義,unsafePerformIO'就是* unsafe *,如果你使用它,東西*將會中斷。 (好吧,除非你非常非常小心,但可能也是如此。) – 2012-02-26 00:07:42
如果你在'main'的末尾添加延遲,你會得到相同的結果嗎?一旦主線程完成,所有其他線程都會被終止,所以根據事情的計劃方式,這可能什麼都不做 - 獨立於與'unsafePerformIO'相關的任何問題。 – hammar 2012-02-26 00:19:45
@hammar你是對的!我在main的最後添加了threadDelay,現在一切正常。謝謝!如果你把它作爲一個單獨的答案,我會接受它。 – 2012-02-26 00:26:58