multithreading - 如何使用安全异常库捕获异步异常?

标签 multithreading haskell exception thread-exceptions

我正在尝试使用 Haskell 构建并发且健壮的代码,建议我使用 safe-exceptionsasync图书馆。但是,我很难理解如何处理异步操作中引发的非 fatal error 。

例如,如果有一个简单的循环每n秒检查一次网络资源,那么使用cancel函数来停止它是有意义的,这会导致在单独的线程中抛出一个 AsyncCancelled 异常。当然,由于网络故障或其他问题,线程内也有可能抛出 IOError 。根据异常的类型及其包含的数据,我想控制单独的线程是否忽略异常、执行某些操作、停止或在主线程中引发异常。

使用安全异常库,唯一能够执行此操作的函数是catchAsync 和其他类似函数,这些函数在文档中被标记为危险。除此之外,异步库中有 waitCatch,但是当我尝试提取 IOError 时,fromException 函数总是返回 Nothing :

{-# 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 ,或者是否有其他方法来处理我尚未发现的此类情况?

最佳答案

请注意 Control.Exception.Safe.throwTo wraps同步异常放入 AsyncExceptionWrapper 中,并且 IOError 是同步的。 (我不知道为什么这种包装是必要的,无论如何你都不应该异步抛出同步异常。)

要使代码正常工作,您应该捕获 AsyncExceptionWrapper 或使用 Control.Exception.throwTo。但实际上我并不完全理解你想要做什么,很可能你把事情变得过于复杂了。

关于multithreading - 如何使用安全异常库捕获异步异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50581476/

相关文章:

python - python asyncio call_soon_threadsafe 真的是线程安全的吗?

multithreading - 为什么 Rust 会阻止多重可变引用?

java - Android 中线程的实现不起作用

function - Haskell:应用翻转两次(翻转类型)

haskell - 如何使用符号创建类型级别列表来测试类型系列

vb.net - 如何在 vb.net 中捕获/处理数字格式异常?

c# - 多线程性能提升

java - 为什么引入 Autocloseable 而不是扩展 Closeable 中可能出现的异常

c++ - Unicode 异常类

haskell - 使用列表推导的列表子列表