gpt4 book ai didi

multithreading - 并发(多线程)程序挂起,除非我打印出一些东西

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

我有一个函数,可以使用forkIO派生到线程中。该函数在ReaderT monad transformer中运行,以便我可以传递只读配置记录:

main :: IO ()
main = do
...
forkIO $ runReaderT watcher config

watcher函数使用 tryTakeMVar监视MVar(我不想阻止它)。MVar存储在配置中,并称为“抽屉”,因为它的行为就像 mainwatcher正在监视的线程之间的事务抽屉一样,基本上是一个跳过 channel
printThing具有 printThing :: Thing -> ReaderT Config IO ()的签名,并调用 putStrLn来打印 Thing
watcher :: ReaderT Config IO ()                                                                                                                                                                       
watcher = do
cfg <- ask
mNewThing <- liftIO $ tryTakeMVar $ drawer cfg
case mNewThing of
Nothing -> do
--liftIO $ putStr "" -- uncommenting this helps
watcher
Just newThing -> do
printThing newThing
watcher

问题是程序在运行时挂起。它似乎陷入了循环。在 putStr ""中调用 main并没有帮助,但是,在 putStr ""中调用 watcher确实会触发线程-它会按预期开始旋转并打印出 Thing

我所能想到的是,我被懒惰所咬,但是我不确定在哪里。我尝试过在可能的情况下使用 $!

我在watcher的某些条件下执行IO操作,但不是全部。那是问题吗?我需要在所有条件分支中执行IO操作吗?

如果有帮助,在将所有内容都包裹在 ReaderT转换器中之前,我没有这个问题。我只是传递 config作为参数。

最佳答案

尽管您的问题中有文字说明,但我还是建议您让watcher阻止。确实很少需要对MVar进行非阻塞操作。通常希望它是sign you haven't quite internalized the "fork everything" mentality。所以:

watcher :: ReaderT Config IO ()
watcher = do
cfg <- ask
newThing <- liftIO . takeMVar $ drawer cfg
printThing newThing
watcher

我们可以单独解决一个问题,形式为“我如何实现效果X,在我看来,这仅需要使用阻塞操作,而是需要非阻塞操作?”如果您要编写一个单独的问题,其中包含有关效果X的一些详细信息。

旁注:我很想用以下方式写上面的内容,虽然含义相同,但从美学角度来说更吸引我:
watcher = forever (asks drawer >>= liftIO . takeMVar >>= printThing)

关于multithreading - 并发(多线程)程序挂起,除非我打印出一些东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56734536/

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