【问题标题】:Canceling an Async thread from within the thread itself从线程本身中取消异步线程
【发布时间】:2017-07-28 15:05:37
【问题描述】:

有没有办法在用async 包中的async 调用的线程中使用cancel?我可以看到你可以从线程外部取消它,但我想知道是否有一个 cancelSelf :: IO () 函数可以停止它自己的执行。我可以将一些东西与唯一的 id 生成和Async 线程引用的共享Map 一起装订在一起,线程本身可以引用这些引用,但这似乎太多了。我可以逃脱未捕获的异常之类的吗?

【问题讨论】:

  • 在我看来,既然您提议的 cancelSelf 函数需要您在要取消的点处处于 IO 中,那么在 EitherT String IO 中同样容易,然后通过返回Left "cancelled" 或其他什么来“取消”。

标签: multithreading haskell asynchronous cancellation


【解决方案1】:

异步操作可以自行取消。不过,这涉及到一些技巧。

{-# 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 块内创建一组相互递归的定义,即使其中一些定义与 &lt;- 绑定,而一些定义在 let 语句中。与往常一样,如果涉及真正的循环,计算就会出现分歧。但在很多情况下,您只想像上面的示例一样引用其他名称,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

【讨论】:

  • "mfix f 只执行一次操作f,最终输出作为输入反馈。因此f 不应该是严格的,因为那样mfix f 会发散"。是的,以一种非常糟糕的方式 - 它会阻止takeMVar
猜你喜欢
  • 1970-01-01
  • 2015-06-02
  • 1970-01-01
  • 2018-05-31
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 2010-12-22
  • 1970-01-01
相关资源
最近更新 更多