2013-05-22 12 views
11
import Control.Concurrent 
main = do 
    forkIO $ putStrLn "123" 
    forkIO $ putStrLn "456" 

Napisałem powyższy kod. Ale kiedy ją wykonałem, zawsze miałem tylko 123. 456 nie jest drukowany. Chyba dlatego, że główny wątek zakończył się przed drugim wątkiem, więc cały program właśnie się skończył.Jak mogę się upewnić, że główny wątek kończy się po zakończeniu wszystkich pozostałych wątków?

Jak mogę temu zapobiec? Każdy api może upewnić się, że główny wątek zakończył się po zakończeniu wszystkich wątków?

OS: OS X 10.8.3

kompilator: ghc 7.4.2

Odpowiedz

15

Użyj async biblioteka:

import Control.Concurrent.Async 

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

Jest to równoważne rozwiązania Daniela, z wyjątkiem dwóch niewielkie zalety:

  • To gwarantuje, że wszelkie wyjątki podniesione w rozdwojonych wątków dostać przebił w wątku nadrzędnego bez powodowania impasu
  • To wygodniejsze
+3

3) Łatwo jest zrozumieć kogoś, kto pochodzi z innego języka. "async" i "wait" mają łatwo zrozumiałe znaczenie angielskie. Z drugiej strony ">> putMvar done()" i "takeMvar done" są niezrozumiałe. – 7stud

+4

lub "współbieżnie (putStrLn" 123 ") (putStrLn" 456 ")' – JJJ

9
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) 
+13

Strzeż problemów z wyjątkami, choć. Jeśli wyjątek uniemożliwia wątkowi dziecięcemu wywoływanie 'putMVar', otrzymasz' BlockedIndefinitelyOnMVar' w głównym wątku. Możesz użyć ['forkFinally'] (http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html#v:forkFinally), aby wywołać komendę' putMVar'. – hammar

Powiązane problemy