gpt4 book ai didi

exception-handling - Async.Catch 对 OperationCanceledException 不起作用

转载 作者:行者123 更新时间:2023-12-04 14:59:53 25 4
gpt4 key购买 nike

我使用 Async.Catch 来处理异步工作流抛出的异常:

work
|> Async.Catch
|> Async.RunSynchronously
|> fun x -> match x with
| Choice1Of2 _ -> () // success
| Choice2Of2 ex -> // failure, handle exception

今天我注意到 Async.Catch 没有处理 OperationCanceledExceptions。而不是从 Async.Catch 获得一个选择,异常不断冒泡,直到它击中我。我预计以下测试是红色的,但它是绿色的:
  [<Test>]
let ``Async.Catch doesnt work on OperationCancelledExceptions``() =
use cancellationTokenSource = new System.Threading.CancellationTokenSource(1000)

let work = async {
while true do
do! Async.Sleep 100
}

(fun () -> work
|> Async.Catch
|> fun x -> Async.RunSynchronously (x, cancellationToken=cancellationTokenSource.Token)
|> ignore)
|> should throw typeof<System.OperationCanceledException>

使用 Async.Catch + Choices + 匹配评估一些异常以及使用 try/catch 块的其他一些异常似乎不正确......它看起来如下所示,这太复杂了。除此之外,我想知道 Async.Catch 有什么用,因为无论如何我都必须使用 try/catch 块...:
  [<Test>]
let ``evaluating exceptions of async workflows``() =
use cancellationTokenSource = new System.Threading.CancellationTokenSource(1000)

let work = async {
while true do
do! Async.Sleep 100
}

try
work
|> Async.Catch
|> fun x -> Async.RunSynchronously (x, cancellationToken=cancellationTokenSource.Token)
|> fun x -> match x with
| Choice1Of2 result -> () // success, process result
| Choice2Of2 ex -> () // failure, handle exception
with ex -> () // another failure, handle exception here too

处理异步工作流异常的最佳方法是什么?我应该转储 Async.Catch 并在任何地方使用 try/catch 块吗?

最佳答案

取消是异步计算中的一种特殊异常。当工作流被取消时,这也会取消所有子计算(取消 token 是共享的)。因此,如果您可以将取消作为普通异常处理,它仍然可以取消计算的其他部分(并且很难推理正在发生的事情)。

但是,您可以编写一个原语来启动工作流(并将其与父工作流分开),然后在此子工作流中处理取消。

type Async = 
static member StartCatchCancellation(work, ?cancellationToken) =
Async.FromContinuations(fun (cont, econt, _) ->
// When the child is cancelled, report OperationCancelled
// as an ordinary exception to "error continuation" rather
// than using "cancellation continuation"
let ccont e = econt e
// Start the workflow using a provided cancellation token
Async.StartWithContinuations( work, cont, econt, ccont,
?cancellationToken=cancellationToken) )

用法类似 Async.Catch ,但您必须将取消 token 传递给 StartCatchCancellation而不是将它传递给主 RunSynchronously (因为工作流是单独启动的):
let work = 
async { while true do
do! Async.Sleep 100 }

let ct = new System.Threading.CancellationTokenSource(10000)
Async.StartCatchCancellation(work, ct.Token)
|> Async.Catch
|> Async.RunSynchronously
|> printfn "%A"

关于exception-handling - Async.Catch 对 OperationCanceledException 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18274986/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com