Async.Catch不工作在OperationCanceledExceptions [英] Async.Catch doesnt work on OperationCanceledExceptions

查看:167
本文介绍了Async.Catch不工作在OperationCanceledExceptions的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Async.Catch处理异步工作流引发的异常:

I use Async.Catch to handle exceptions thrown by async workflows:

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

今天我注意到OperationCanceledExceptions不由Async.Catch处理。而不是从Async.得到一个选择。异常保持冒泡,直到它触及我。我预计以下测试是红色的,但它是绿色的:

Today I noticed that OperationCanceledExceptions aren't handled by Async.Catch. Instead of getting a Choice from Async.Catch the exception keeps bubbling up until it hits me. I expected the following test to be red, but it's green:

  [<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 +选择+匹配和其他一些使用try / catch块评估某些异常doesn'看起来不错...看起来像下面这样太复杂了。此外,我不知道Async.Catch有什么用,因为我必须使用try / catch块...:

Evaluating some exceptions with Async.Catch + Choices + matching and some others using try/catch blocks doesn't seem right... it would look like the following, which is way too complicated. Besides that I wonder what use Async.Catch has, since I have to use a try/catch block anyway...:

  [<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块吗?

What's the best way to handle exceptions of async workflows? Should I just dump Async.Catch and use try/catch blocks everywhere?

推荐答案

异步计算中取消是一种特殊的例外。当取消工作流时,这也会取消所有的子计算(取消令牌是共享的)。因此,如果您可以将取消作为一个普通例外,它仍然可以取消计算的其他部分(并且很难说明发生了什么)。

Cancellation is a special kind of exception in asynchronous computations. When a workflow is cancelled, this also cancels all child computations (the cancellation token is shared). So, if you could handle cancellation as an ordinary exception, it could still cancel some other parts of your computation (and it would be hard to reason about what is going on).

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

However, you can write a primitive that starts a workflow (and separates it from the parent workflow) and then handles cancellation in this sub-workflow.

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 类似,但您必须将取消令牌传递给 StartCatchCancellation 而不是将其传递给主要的 RunSynchronously (因为工作流是单独启动的):

The usage is similar to Async.Catch, but you have to pass the cancellation token to StartCatchCancellation rather than passing it to the main RunSynchronously (because the workflow is started separately):

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"

这篇关于Async.Catch不工作在OperationCanceledExceptions的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆