从线程本身取消异步线程
Canceling an Async thread from within the thread itself
有没有办法在使用 async 包中的 async
调用的线程中使用 cancel
?我可以看到你可以从线程外部取消它,但我想知道是否有一个 cancelSelf :: IO ()
函数可以停止它自己的执行。我 可以 将一些东西与唯一 ID 生成和共享 Map
的 Async
线程引用结合在一起,线程本身可以引用,但这似乎太多了。我可以逃避未捕获的异常吗?
异步操作可以自行取消。不过,它涉及到一些技巧。
{-# LANGUAGE RecursiveDo #-}
import Control.Concurrent.Async
main :: IO ()
main = do
rec let doCancel = cancel calculate
calculate <- async doCancel
wait calculate
理论上,你可以在没有 RecursiveDo
的情况下做到这一点,但我从来不想手动编写 mfix
表达式(RecursiveDo
绑定去糖)。
RecursiveDo
允许您在 do 块内创建一组相互递归的定义,即使某些定义与 <-
绑定并且某些定义在 [=17= 内也是如此] 陈述。与往常一样,如果涉及到真正的循环,计算就会出现分歧。但是在很多情况下,您想要做的就是能够像上面的示例一样引用其他名称,并且 RecursiveDo
工作得很好。
哦,the implementation of mfix
for IO
太可怕了。我很高兴我不必自己写。
-- 编辑--
由于几乎没有收到任何反馈,我意识到如何使用它来解决您的问题并不完全清楚。所以这是一个扩展示例,它使用组合器生成可以取消自身的 Async
:
{-# LANGUAGE RecursiveDo #-}
-- obviously want the async library
import Control.Concurrent.Async
-- used in selfCancelableAsync
import Control.Monad (forever)
import Control.Concurrent (threadDelay)
-- only used for demonstration
import System.Random (randomIO)
main :: IO ()
main = do
a <- selfCancelableAsync $ \selfCancel -> do
choice <- randomIO
if choice then return "Success!" else selfCancel
result <- wait a
putStrLn result
-- spawns an Async that has the ability to cancel itself by
-- using the action passed to the IO action it's running
selfCancelableAsync :: (IO a -> IO b) -> IO (Async b)
selfCancelableAsync withCancel = do
rec let doCancel = do
cancel calculate
-- This must never return to ensure it has the correct type.
-- It uses threadDelay to ensure it's not hogging resources
-- if it takes a moment to get killed.
forever $ threadDelay 1000
calculate <- async $ withCancel doCancel
return calculate
有没有办法在使用 async 包中的 async
调用的线程中使用 cancel
?我可以看到你可以从线程外部取消它,但我想知道是否有一个 cancelSelf :: IO ()
函数可以停止它自己的执行。我 可以 将一些东西与唯一 ID 生成和共享 Map
的 Async
线程引用结合在一起,线程本身可以引用,但这似乎太多了。我可以逃避未捕获的异常吗?
异步操作可以自行取消。不过,它涉及到一些技巧。
{-# LANGUAGE RecursiveDo #-}
import Control.Concurrent.Async
main :: IO ()
main = do
rec let doCancel = cancel calculate
calculate <- async doCancel
wait calculate
理论上,你可以在没有 RecursiveDo
的情况下做到这一点,但我从来不想手动编写 mfix
表达式(RecursiveDo
绑定去糖)。
RecursiveDo
允许您在 do 块内创建一组相互递归的定义,即使某些定义与 <-
绑定并且某些定义在 [=17= 内也是如此] 陈述。与往常一样,如果涉及到真正的循环,计算就会出现分歧。但是在很多情况下,您想要做的就是能够像上面的示例一样引用其他名称,并且 RecursiveDo
工作得很好。
哦,the implementation of mfix
for IO
太可怕了。我很高兴我不必自己写。
-- 编辑--
由于几乎没有收到任何反馈,我意识到如何使用它来解决您的问题并不完全清楚。所以这是一个扩展示例,它使用组合器生成可以取消自身的 Async
:
{-# LANGUAGE RecursiveDo #-}
-- obviously want the async library
import Control.Concurrent.Async
-- used in selfCancelableAsync
import Control.Monad (forever)
import Control.Concurrent (threadDelay)
-- only used for demonstration
import System.Random (randomIO)
main :: IO ()
main = do
a <- selfCancelableAsync $ \selfCancel -> do
choice <- randomIO
if choice then return "Success!" else selfCancel
result <- wait a
putStrLn result
-- spawns an Async that has the ability to cancel itself by
-- using the action passed to the IO action it's running
selfCancelableAsync :: (IO a -> IO b) -> IO (Async b)
selfCancelableAsync withCancel = do
rec let doCancel = do
cancel calculate
-- This must never return to ensure it has the correct type.
-- It uses threadDelay to ensure it's not hogging resources
-- if it takes a moment to get killed.
forever $ threadDelay 1000
calculate <- async $ withCancel doCancel
return calculate