指定无限循环的毫秒速度

时间:2015-08-09 03:59:24

标签: haskell concurrency

我的主函数有一个无限循环,我想每100毫秒执行一次循环。我知道它是由一些并发或并行方法完成的,但我以前从未做过这样的事情,甚至不知道从哪里开始。你会如何实现这样的功能?

3 个答案:

答案 0 :(得分:9)

假设您的循环体占用的时间可以忽略不计,请使用threadDelay中的Control.Concurrent

import Control.Concurrent

main = forever $ do
  mainBody
  threadDelay (100*1000) -- value in microseconds

更新:要考虑循环体的时间,请使用:

import Data.Time.Clock
import Control.Concurrent
import Control.Monad

mainBody :: IO ()
mainBody = putStrLn "hi"

main = forever $ do
  start <- getCurrentTime
  mainBody
  end <- getCurrentTime
  let diff = diffUTCTime end start
      usecs = floor (toRational diff * 1000000) :: Int
      delay = 100*1000 - usecs
  if delay > 0
    then threadDelay delay
    else return ()

答案 1 :(得分:3)

Haskell的线程重量轻,因此快速解决方案是在每个周期进行分叉。因此,您最终将主线程用作工作线程的管理器,这可确保每100个微处理器生成一个工作线。

import Control.Concurrent

main = 
  forever $ do
    forkIO $ loopCycle
    threadDelay $ 100 * 10^3

如果您关心的异常不会迷失并在主线程中重新加注,我建议您查看the "slave-thread" package。实际上,我建议默认使用该软件包而不是forkIO和兄弟,但我是作者,所以我可能是主观的。

另请注意,上述解决方案可能会导致工作线程累积,以防loopCycle执行时间超过100微秒。为了防止出现这种情况,您可以在管理器线程中实施策略,这将确保活动工作者的数量有限。以下是如何实施这样的战略:

-- From the "SafeSemaphore" package
import qualified Control.Concurrent.SSem as Sem

main =
  manager 12 (100 * 10^3) $ putStrLn "Implement me!"

manager :: Int -> Int -> IO () -> IO ()
manager limit delay worker =
  do
    sem <- Sem.new limit
    forever $ do
      forkIO $ Sem.withSem sem $ worker
      threadDelay delay

答案 2 :(得分:1)

您可以使用sleep在每次迭代结束时暂停循环100毫秒。 https://www.haskell.org/hoogle/?q=sleep