throwTo
在另一个线程中引发任何异常:
为了能够编写具有保证的代码,例如“在获取锁之后始终会释放锁”,我们使用throwTo :: Exception e => ThreadId -> e -> IO ()
throwTo
raises an arbitrary exception in the target thread (GHC only).
mask
来运行计算过程中仅在阻塞时才能接收到异步异常的代码:
mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
Executes an IO computation with asynchronous exceptions masked. That is, any thread which attempts to raise an exception in the current thread with
throwTo
will be blocked until asynchronous exceptions are unmasked again.
同时还需要一个更强的uninterruptibleMask
,在该掩码计算期间将完全不会触发异步异常:
uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
Like
mask
, but the masked computation is not interruptible
遮罩是用于实现更高级的抽象,如 括号
:
如果我理解正确,Python 有一种(不太通用的)异步异常形式,最显著的表现是
bracket :: IO a -- computation to run first ("acquire resource") -> (a -> IO b) -- computation to run last ("release resource") -> (a -> IO c) -- computation to run in-between -> IO c -- returns the value from the in-between computation
When you want to acquire a resource, do some work with it, and then release the resource, it is a good idea to use
bracket
, becausebracket
will install the necessary exception handler to release the resource in the event that an exception is raised during the computation. If an exception is raised, thenbracket
will re-raise the exception (after performing the release).
KeyboardInterrupt
:引发原因是用户按下中断键(通常是 Control-C 或 Delete)。在执行过程中,会定期检查是否有中断。
文档对“检查中断”的时间并没有明确说明,但它似乎意味着
KeyboardInterrupt
可能在程序执行的 任何 点上被触发。因此,Python 的异步异常具有保持正确性的所有相同微妙困难。例如,考虑以下模式:
x = None
try:
x = acquire()
do_something(x) # (1)
finally:
if x is not None: # (2)
release(x)
如果在
(1)
过程中出现任何异常,那么我们可以确保 finally
块的内容将被执行。但是如果在 (2)
过程中出现 KeyboardInterrupt
异常会发生什么呢?在存在异步异常的情况下,似乎根本无法保证资源清理,除非有一种屏蔽它们的方法。是否有此类工具,或者我们依赖于 鸵鸟算法?