Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capture exception in Async.Start?

Tags:

f#

I have the following code. And I want to run without blocking the main thread.

let post () = .....
try
    let response = post ()
    logger.Info(response.ToString())
with 
| ex -> logger.Error(ex, "Exception: " + ex.Message)

So I changed the code to the following. However, how to catch the exception in post?

let post = async { 
   ....
   return X }
try
    let response = post |> Async.StartChild
    logger.Info(response.ToString())
with 
| ex -> logger.Error(ex, "Exception: " + ex.Message)
like image 629
ca9163d9 Avatar asked Aug 15 '16 22:08

ca9163d9


2 Answers

One way is to use Async.Catch in a calling workflow. Given a couple of functions (a throwaway "async" function and something to work with the result):

let work a = async {
    return 
        match a with 
        | 1 -> "Success!"
        | _ -> failwith "Darnit"
}

let printResult (res:Choice<'a,System.Exception>) = 
    match res with
    | Choice1Of2 a -> printfn "%A" a
    | Choice2Of2 e -> printfn "Exception: %s" e.Message

One can use Async.Catch

let callingWorkflow = 
    async {
        let result = work 1 |> Async.Catch
        let result2 = work 0 |> Async.Catch

        [ result; result2 ]
        |> Async.Parallel
        |> Async.RunSynchronously
        |> Array.iter printResult
    }

callingWorkflow |> Async.RunSynchronously

Async.Catch returns a Choice<'T1,'T2>. Choice1Of2 for a successful execution, and the exception thrown for the Choice2Of2.

like image 82
jdphenix Avatar answered Sep 28 '22 18:09

jdphenix


You'd put the try/catch in an async block as well

let post = async { .... }
async {
  try
    let! response = post
    logger.Info(response.ToString())
  with 
  | ex -> logger.Error(ex, "Exception: " + ex.Message)
} |> Async.Start
like image 40
Dax Fohl Avatar answered Sep 28 '22 18:09

Dax Fohl