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

Ho scritto il codice sopra. Ma quando l'ho eseguito, ho sempre ricevuto solo 123. 456 non viene stampato. Suppongo che sia perché il thread principale è finito prima dell'altro thread, quindi l'intero programma è appena finito.Come posso assicurarmi che il filo principale termini dopo che tutti gli altri fili sono finiti?

Come posso evitare questo? Qualsiasi API può assicurarsi che il thread principale sia terminato dopo che tutti i thread sono terminati?

OS: OS X 10.8.3

compilatore: GHC 7.4.2

risposta

15

utilizzare la libreria async:

import Control.Concurrent.Async 

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

Ciò equivale a una soluzione di Daniel, se non con due piccoli vantaggi:

  • assicura che tutte le eccezioni sollevate nelle filettature biforcute ottenere re-sollevati nella discussione genitore senza causare un deadlock
  • È più conveniente
+3

3) È facile per qualcuno che viene da un'altra lingua capire. "async" e "wait" hanno facilmente inteso i significati inglesi. D'altra parte, ">> putMvar done()" e "takeMvar done" sono incomprensibili. – 7stud

+4

o 'contemporaneamente (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

Attenzione di problemi con eccezioni, però. Se un'eccezione impedisce a un thread figlio di chiamare 'putMVar', nel thread principale verrà visualizzato un' BlockedIndefinitelyOnMVar'. Puoi usare ['forkFinally'] (http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html#v:forkFinally) per assicurarti che" putMVar' venga chiamato. – hammar

Problemi correlati