0

Running this code:

open System
async {
 printfn "a"
 do!
 Async.Parallel [|
 Async.FromContinuations ignore // Sleep forever
 async { return raise (Exception("Kaboom")) }
 |]
 |> Async.Ignore<unit array>
 printfn "b"
}
|> Async.RunSynchronously

Gives this output:

a

printfn "b" is never reached and the program appears to hang.

Why is this?

Shouldn't the exception cause the program to crash?

asked Mar 7 at 13:04
5
  • 1
    Just adding to below answer, see fsharp.github.io/fsharp-core-docs/reference/…. Remember that ignore takes any value and returns unit. In this case, the value passed to it is the triplet of continuation functions. As per the docs, you must call one of these.
    Jim Foye
    Commented Mar 7 at 13:53
  • @JimFoye Async.FromContinuations ignore is intended to be an async that sleeps forever - perhaps this is a bad implemenation? Should it sleep until cancellation is triggered?
    sdgfsdh
    Commented Mar 7 at 14:15
  • If you want to sleep, use Async.Sleep. If you create a computation with Async.FromContinuations you must (as the docs say) eventually call one of the three continuation functions that are passed to your function.
    Jim Foye
    Commented Mar 7 at 14:57
  • What I'm looking for is Async.Sleep for an infinite time
    sdgfsdh
    Commented Mar 7 at 17:52
  • OK just pass TimeSpan.MaxValue to Async.Sleep. It will wake up in about 30,000 years, but when that happens you could just loop and call it again.
    Jim Foye
    Commented Mar 7 at 19:17

1 Answer 1

2

The behavior you're observing is due to how Async.Parallel and Async.FromContinuations work together in F#

Async.FromContinuations:The ignore function you passed to Async.FromContinuations effectively ignores the continuations, meaning it never completes or raises an exception.

Async.Parallel: This function runs multiple asynchronous workflows in parallel and waits for all of them to complete. The key word here is "Waits for all". If any of the workflows raise an exception,Async.Parallel will propagate the exception.

Since Async.FromContinuations ignore never completes, Async.Parallel waits indefinitely for it to finish. This causes the entire asynchronous workflow to hang, and printfn "b" is never reached.

So the only way to fix this is by ensuring that all workflows in Async.Parallel can complete or handle exceptions properly. Something like below:

open System
async {
 printfn "a"
 try
 do!
 Async.Parallel [|
 async {
 // Simulate some work
 do! Async.Sleep 1000
 }
 async {
 return raise (Exception("Kaboom"))
 }
 |]
 |> Async.Ignore<unit array>
 with
 | ex -> printfn "Exception: %s" ex.Message
 printfn "b"
}
|> Async.RunSynchronously

The first workflow simulates some work with Async.Sleep, ensuring it completes. The second workflow raises an exception, which is caught by the try...with block, allowing the program to handle the exception and continue to printfn "b" . Hope it helps

answered Mar 7 at 13:41

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.