exception handling - Async.Catch doesnt work on OperationCanceledExceptions -


i use async.catch handle exceptions thrown async workflows:

work |> async.catch |> async.runsynchronously |> fun x -> match x             | choice1of2 _ -> () // success             | choice2of2 ex -> // failure, handle exception 

today noticed operationcanceledexceptions aren't handled async.catch. instead of getting choice async.catch exception keeps bubbling until hits me. expected following test red, it's green:

  [<test>]   let ``async.catch doesnt work on operationcancelledexceptions``() =     use cancellationtokensource = new system.threading.cancellationtokensource(1000)      let work = async {       while true         do! async.sleep 100     }      (fun () -> work                |> async.catch                |> fun x -> async.runsynchronously (x, cancellationtoken=cancellationtokensource.token)                |> ignore)     |> should throw typeof<system.operationcanceledexception> 

evaluating exceptions async.catch + choices + matching , others using try/catch blocks doesn't seem right... following, way complicated. besides wonder use async.catch has, since have use try/catch block anyway...:

  [<test>]   let ``evaluating exceptions of async workflows``() =     use cancellationtokensource = new system.threading.cancellationtokensource(1000)      let work = async {       while true         do! async.sleep 100     }      try       work       |> async.catch       |> fun x -> async.runsynchronously (x, cancellationtoken=cancellationtokensource.token)       |> fun x -> match x                   | choice1of2 result -> () // success, process result                   | choice2of2 ex -> () // failure, handle exception     ex -> () // failure, handle exception here 

what's best way handle exceptions of async workflows? should dump async.catch , use try/catch blocks everywhere?

cancellation special kind of exception in asynchronous computations. when workflow cancelled, cancels child computations (the cancellation token shared). so, if handle cancellation ordinary exception, still cancel other parts of computation (and hard reason going on).

however, can write primitive starts workflow (and separates parent workflow) , handles cancellation in sub-workflow.

type async =    static member startcatchcancellation(work, ?cancellationtoken) =      async.fromcontinuations(fun (cont, econt, _) ->       // when child cancelled, report operationcancelled       // ordinary exception "error continuation" rather       // using "cancellation continuation"       let ccont e = econt e       // start workflow using provided cancellation token       async.startwithcontinuations( work, cont, econt, ccont,                                      ?cancellationtoken=cancellationtoken) ) 

the usage similar async.catch, have pass cancellation token startcatchcancellation rather passing main runsynchronously (because workflow started separately):

let work =    async { while true             do! async.sleep 100 }  let ct = new system.threading.cancellationtokensource(10000) async.startcatchcancellation(work, ct.token)  |> async.catch |> async.runsynchronously  |> printfn "%a" 

Comments

Popular posts from this blog

assembly - 8086 TASM: Illegal Indexing Mode -

Java, LWJGL, OpenGL 1.1, decoding BufferedImage to Bytebuffer and binding to OpenGL across classes -

javascript - addthis share facebook and google+ url -