如何可靠地检查线程是否仍在运行?

6

我目前使用以下代码启动工作线程。

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

即在后台开始执行一些工作,并返回一个IO操作,让调用者轮询工作线程是否仍在运行或因某种原因停止。

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

2个回答

7

创建线程后,但在“void work`finally`writeIORef running False”开始之前,异步异常可能会被触发。使用forkFinally来处理这个问题。

我可以想象还有其他问题。我建议使用async库。它为您处理所有复杂性。使用 poll 检查 Async 状态。


5

关于Yuras的回答,Simon Marlow的书中Mask and forkIO section解释了初始掩码状态可能存在一些问题。正如他所解释的:

经验法则是,在forkIO中调用任何异常处理函数时,最好使用forkFinally来编写。特别是,如果你发现自己正在编写forkIO (xfinallyy),那么应改为编写forkFinally x (\_ -> y),更好的方法是使用Async API,它会为您处理这些细节。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接