超时时如何重试阻止IO操作?

时间:2018-08-23 09:28:28

标签: haskell io retry-logic

在Haskell中如何处理阻塞的IO动作?如何将这个IO动作放到一个范围内,并通过另一种方法来管理这个范围?如果达到超时,我将重新调用此方法。通常,在其他语言中,如果我在可配置的时间内未得到结果,我可能会将其放在单独的线程中,并abort放入它。 (计时器是外部计时器。)

在我的情况下:我有多个retries,并且我想在超时的情况下执行IO操作。如何且仅当IO的数目大于0时,才将retries动作放在超时范围内,以便在超时到期后重新调用它。

基本上:给定我们的IO动作,例如ioMethod::IO String(我尚未在Haskell的套接字库中查看过),我们将其假设为黑框,

module Retry where

import IOExternal(ioMethod)

retryFunc :: Int -> IO String
retryFunc retries=do
            msg<-retry 5 100 IOExternal 
            return msg

retry :: Int -> Int -> IOExternal -> IO String
retry retries timeout ioMethod = go retries timeout "" where
        go 0       timeout ioMethod  msg =
                    if msg=="" then return "Max Retries reached" 
                               else return msg

        go retries timeout ioMethod  msg counter
               = gogo retries timeout counter msg  where
                     gogo retries timeout 0 msg = return ""
                     gogo retries timeout counter msg
                        = ioMethod>>=gogo retries timeout counter-1 

我不知道如何为最后一条条件/线建模。

PS 我还不熟悉Haskell中的线程(这里是初学者),并且我确实认为超时范围应该在不同的线程中执行,因此我需要从主线程检查它程序,然后调用它(如果retries> 0)或结束main方法。

1 个答案:

答案 0 :(得分:3)

您可以使用timeout向任何阻塞调用添加超时,并为重试提供简单的递归:

retry :: Int -> Int -> IO a -> IO (Maybe a)
retry 0 _ _ = return Nothing
retry numRetries microseconds action = do
    result <- timeout microseconds action
    case result of
        Nothing -> retry (numRetries-1) microseconds action
        Just a  -> return (Just a)

不过,请阅读有关FFI内容警告的文档。