4Manuals

  • PDF Cloud HOME

支架在线程内时不会释放资源 Download

    Tensorflow多线程推理比单线程推理慢 中断可运行线程的问题 有没有办法在Haskell中获得列表的所有可能的重排? 如果导入了外部包,则GHCi无法加载导入Data.Set或Data.Maybe的脚本 ThreadPool实现c Data.Set成员并行查找 java.lang.OutOfMemoryError:无法在handlerthread.start()上分配JNI Env 最低订购要求 有什么方法可以检查套接字连接是否可用? 我该如何回答第一章第18章练习5,Haskell,而不是练习6中的“ flipType”

我在处理Haskell的bracket时遇到麻烦:当在派生线程中运行(使用forkFinally)@DslMarker的第二个参数时,释放资源的计算在以下情况下不运行程序结束。

以下代码说明了此问题(我知道在这种特定情况下,我可以禁用缓冲功能以立即写入文件):

bracket

从不释放资源(并写入控制台)的计算:

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

通过从putStrLn $ "\nClosing handle " ++ show fileHandle hClose fileHandle 中删除派生代码来使程序成为单线程,可以解决此问题,并在使用 Ctrl + c结束程序时关闭文件句柄kbd>:

main

使用多个线程时,如何确保执行main = writeToFile "first_file" 中的资源释放代码?

2 个答案:

答案 0 :(得分:5)

此问题的根本原因是,当main退出时,您的进程将终止。它不会等待您创建的任何其他线程来完成。因此,在您的原始代码中,您创建了一个线程来写入文件,但是不允许完成该线程。

如果您想杀死线程但要强制清理线程,请像在此一样使用throwTo。如果您希望线程完成,则需要等待main返回之前。参见How to force main thread to wait for all its child threads finish in Haskell

答案 1 :(得分:5)

使用throwTo

显然,用bracket创建的线程永远不会抛出异常,因此forkFinally的资源释放代码也永远不会执行。

我们可以使用bracket手动完成此操作:

throwTo threadId ThreadKilled



Similar searches
    docker:来自守护程序的错误响应…出了什么事? 如何使用JavaScript从一个HTML页面到另一个HTML页面获取数据? 使用Express连接到SQL Server(React项目) 使用MySQL查询JSON数组 REGEXP_SUBSTR Oracle |提取两个定界符之间的字符串