Async.Catch doesnt work on OperationCanceledExceptions

后端 未结 1 1068
独厮守ぢ
独厮守ぢ 2021-01-05 06:05

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

work
|> Async.Catch
|> Async.RunSynchronously
|> fun x -> match x with
                 


        
相关标签:
1条回答
  • 2021-01-05 06:59

    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) )
    

    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"
    
    0 讨论(0)
提交回复
热议问题