Ich habe Probleme mit Haskell's bracket
: Wenn das zweite Argument in einem gegabelten Thread (unter Verwendung forkFinally
) ausgeführt wird bracket
, wird die Berechnung, die Ressourcen freigibt, nicht ausgeführt, wenn das Programm endet.
Hier ist Code, der das Problem veranschaulicht (mir ist bewusst, dass ich in diesem speziellen Fall die Pufferung deaktivieren kann, um sofort in die Datei zu schreiben):
import System.IO
import Control.Exception ( bracket
, throwTo
)
import Control.Concurrent ( forkFinally
, threadDelay
)
main = do
threadId <- forkFinally
(writeToFile "first_file")
(\ex -> putStrLn $ "Exception occurred: " ++ show ex)
putStrLn "Press enter to exit"
_ <- getLine
putStrLn "Bye!"
writeToFile :: FilePath -> IO ()
writeToFile file = bracket
(openFile file AppendMode)
(\fileHandle -> do
putStrLn $ "\nClosing handle " ++ show fileHandle
hClose fileHandle
)
(\fileHandle -> mapM_ (addNrAndWait fileHandle) [1 ..])
addNrAndWait :: Handle -> Int -> IO ()
addNrAndWait fileHandle nr =
let nrStr = show nr
in do
putStrLn $ "Appending " ++ nrStr
hPutStrLn fileHandle nrStr
threadDelay 1000000
Die Berechnung, die Ressourcen freigibt (und in die Konsole schreibt), wird niemals aufgerufen:
putStrLn $ "\nClosing handle " ++ show fileHandle
hClose fileHandle
Wenn Sie das Programm durch Entfernen des Forking-Codes zu einem einzelnen Thread machen, wird main
das Problem behoben, und das Dateihandle wird geschlossen, wenn Sie das Programm mit Ctrl+ beenden c:
main = writeToFile "first_file"
Wie stelle ich sicher, dass der Code zur Ressourcenfreigabe in bracket
ausgeführt wird, wenn mehrere Threads verwendet werden?
threadDelay
vor dem Drucken einen hinzufügen"Closing handle"
.)