检查线程是否仍在运行的可靠方法是什么?

sha*_*ang 5 multithreading haskell

我目前正在使用以下代码来启动工作线程.

import Control.Monad      (void)
import Control.Concurrent (forkIO)
import Control.Exception  (finally)
import Data.IORef         (newIORef, writeIORef, readIORef)

startWorker :: IO a -> IO (IO Bool)
startWorker work = do
    running <- newIORef True
    _ <- forkIO $ void work `finally` writeIORef running False
    return $ readIORef running
Run Code Online (Sandbox Code Playgroud)

即开始在后台进行一些工作并返回一个IO动作,如果工作线程仍在运行或由于某种原因它已停止,则允许调用者轮询.

这种方法有多可靠?是否存在线程在没有调用finally块的情况下死亡的情况(当然,不包括整个进程被杀死的情况)?有没有更好的方法来实现相同的功能?

Yur*_*ras 7

创建线程后,异步异常可能会触发,但在"void work`final`,writeIORef运行False"开始之前.使用forkFinally来处理它.

我可以想象还有其他问题.我推荐异步库.它为您处理所有复杂性.使用poll来检查Async状态.


Dan*_*rro 5

与Yuras的回答相关,初始掩蔽状态可能存在一些问题,正如Simon Marlow的书中的Mask和forkIO部分所解释的那样.他解释说,底线是:

经验法则是任何被称为a中的第一件事的异常处理函数forkIO都可以更好地编写forkFinally.特别是,如果你发现自己forkIO (x最后写作y),那么就写一下forkFinally x (\_ -> y).更好的是,使用Async API,它为您处理这些细节.