gpt4 book ai didi

multithreading - 如何将父异步与多个子异步链接

转载 作者:行者123 更新时间:2023-12-03 12:59:22 25 4
gpt4 key购买 nike

async package的文档将withAsync函数描述为:

Spawn an asynchronous action in a separate thread, and pass its Async handle to the supplied function. When the function returns or throws an exception, uninterruptibleCancel is called on the Async. This is a useful variant of async that ensures an Async is never left running unintentionally.



在过去的两个小时中,我一直在盯着它看,并且一直无法弄清楚如何启动一个监视线程,该监视线程产生了多个工作线程,例如:
  • 如果监视器线程死亡,则应终止所有工作线程,
  • 但是,如果任何工作线程死亡,其他工作线程都不应该受到影响。 应该通知监视器,它应该能够重新启动工作线程。
  • 最佳答案

    似乎我们需要两个功能:一个启动所有异步任务,另一个监视它们并在它们死时重新启动它们。

    第一个可以这样写:

    withAsyncMany :: [IO t] -> ([Async t] -> IO b) -> IO b
    withAsyncMany [] f = f []
    withAsyncMany (t:ts) f = withAsync t $ \a -> withAsyncMany ts (f . (a:))

    如果我们使用 managed包,我们也可以这样写:
    import Control.Monad.Managed (with,managed)

    withAsyncMany' :: [IO t] -> ([Async t] -> IO b) -> IO b
    withAsyncMany' = with . traverse (\t -> managed (withAsync t))

    重新启动功能将循环异步列表,轮询它们的状态,并在它们失败时进行更新:
    {-# language NumDecimals #-}
    import Control.Concurrent (threadDelay)

    resurrect :: IO t -> [Async t] -> IO ()
    resurrect restartAction = go []
    where
    go ts [] = do
    threadDelay 1e6 -- wait a little before the next round of polling
    go [] (reverse ts)
    go past (a:pending) = do
    status <- poll a -- has the task died, or finished?
    case status of
    Nothing -> go (a:past) pending
    Just _ -> withAsync restartAction $ \a' -> go (a':past) pending

    但是,我担心许多嵌套的 withAsyncs导致某种类型的资源泄漏的可能性(因为必须在每种 withAsync上安装某种异常处理程序,以在父线程死亡的情况下通知 child )。

    因此,在这种情况下,最好使用简单的 async生成工作程序,将 Async的集合存储到某种可变引用中,并在监视器线程中安装单个异常处理程序,该异常处理程序将遍历终止每个任务的容器。

    关于multithreading - 如何将父异步与多个子异步链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46776954/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com