Как я могу убедиться, что основная нить заканчивается после окончания всех остальных концов?

import Control.Concurrent
main = do
    forkIO $ putStrLn "123"
    forkIO $ putStrLn "456"

Я написал код выше. Но когда я его выполнил, я всегда получал только 123. 456 не печатается. Я думаю, это потому, что основной поток закончился до другого потока, так что вся программа только что закончилась.

Как я могу это предотвратить? Любой api может удостовериться, что основной поток закончился после того, как закончились все потоки?

ОС: OS X 10.8.3

компилятор: ghc 7.4.2

Ответ 1

Используйте библиотеку async:

import Control.Concurrent.Async

main = do
    a1 <- async $ putStrLn "123"
    a2 <- async $ putStrLn "456"
    mapM_ wait [a1, a2]

Это эквивалентно решению Дэниела, за исключением двух незначительных преимуществ:

  • Он гарантирует, что любые исключения, возникающие в разветвленных потоках, будут повторно подняты в родительском потоке без возникновения тупика.
  • Это более удобно

Ответ 2

import Control.Concurrent
main = do
    done <- newEmptyMVar
    forkIO $ putStrLn "123" >> putMVar done ()
    forkIO $ putStrLn "456" >> putMVar done ()
    takeMVar done
    takeMVar done
    -- OR: replicateM_ 2 (takeMVar done)