我正在尝试使用Haskell构建并发且健壮的代码,建议我使用safe-exceptions和async库。但是,我很难理解如何处理async
动作中抛出的非致命错误。
例如,如果有一个简单的循环每隔 n 秒检查一个网络资源,那么使用导致{{cancel
函数的AsyncCancelled
函数来停止它是有意义的。 1}}在单独的线程中抛出的异常。当然,由于网络出现故障或其他一些问题,也有可能从线程中抛出IOError
。根据异常的类型及其包含的数据,我想控制单独的线程是否忽略异常,执行某些操作,停止或引发主线程中的异常。
使用安全异常库,能够执行此操作的唯一功能是catchAsync
和其他类似功能,在文档中标记为危险。除此之外,异步库中有waitCatch
,但当我尝试提取fromException
时,Nothing
函数始终返回IOError
:
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Concurrent.Async
import Control.Concurrent hiding (throwTo)
import Control.Exception.Safe
import Control.Monad
import System.IO
import System.IO.Error hiding (catchIOError)
main = do
hSetBuffering stdin NoBuffering
putStrLn "Press any key to continue..."
a <- async runLoop
async $ hWaitForInput stdin (-1) *>
throwTo (asyncThreadId a) (userError "error")
waitCatch a >>= either handler nothing
where
printThenWait i = putStr (show i ++ " ") *> threadDelay 1000000
runLoop = sequence_ $ printThenWait <$> [1..]
nothing _ = pure ()
handler e
| Just (e' :: IOError) <- fromException e =
putStrLn "It's an IOError!"
| (Nothing :: Maybe IOError) <- fromException e =
putStrLn "We got Nothing!"
我对从异步异常中恢复的危险感到有些困惑,特别是当cancel
之类的标准函数导致它们被抛出时,我不知道推荐的处理它们的方法是什么使用这两个库时。这是一个推荐catchAsync
的实例,还是有另一种方法来处理我未发现的这类情况?
答案 0 :(得分:1)
请注意,((window) => {
window.lib = {
LibClassBase: class {}
LibClass1: class extends LibClassBase {}
}
})(window)
Control.Exception.Safe.throwTo
和AsyncExceptionWrapper
的IOError
wraps个同步异常是同步。 (我不知道为什么这种包装是必要的,你不应该异步地抛出异步异常。)
要使代码正常工作,您应该抓住AsyncExceptionWrapper
或使用Control.Exception.throwTo
。但实际上我并没有完全明白你想要做什么,很可能是你过于复杂的事情。