stm*_*max 6 f# exception-handling async-workflow
我使用Async.Catch来处理异步工作流抛出的异常:
work
|> Async.Catch
|> Async.RunSynchronously
|> fun x -> match x with
| Choice1Of2 _ -> () // success
| Choice2Of2 ex -> // failure, handle exception
Run Code Online (Sandbox Code Playgroud)
今天我注意到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>
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)
处理异步工作流异常的最佳方法是什么?我应该只是转储Async.Catch并在任何地方使用try/catch块吗?
取消是异步计算中的一种特殊异常.取消工作流时,这也会取消所有子计算(共享取消令牌).因此,如果您可以将取消作为一个普通的例外处理,它仍然可以取消计算的其他部分(并且很难推断出正在发生的事情).
但是,您可以编写启动工作流的基元(并将其与父工作流分开),然后在此子工作流中处理取消.
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) )
Run Code Online (Sandbox Code Playgroud)
用法类似于Async.Catch,但您必须传递取消令牌StartCatchCancellation而不是将其传递给main 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"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
944 次 |
| 最近记录: |