2

I don't understand the semantics of Async.RunSynchronously when given a timeout argument. Why doesn't the following example terminate?

let runInMaxTime (time: int) (work: Async<'T>) =
    try
        Async.RunSynchronously(work,time)
        |> Some
    with
    | _     ->
        None

let rec forever () : unit  = 
    printfn "Forever looping"
    forever ()

// Never terminates
let x = runInMaxTime 10 <| async {return forever ()}

What would a proper implementation of runInMaxTime look like? The only thing I've come up with that works is based on Tasks and cancellation tokens.

esevelos
  • 376
  • 2
  • 8

1 Answers1

6

The timeout and cancellation token cannot arbitrarily stop an async computation, they can only do so when the computation yields, by using let!, do! etc. Your example computation doesn't do that.

This would work as you expect.

let rec forever () : Async<unit> =
    async {
        printfn "Forever looping"
        return! forever()
    }

let x = runInMaxTime 1000 <| forever()
Leaf Garland
  • 3,647
  • 18
  • 18
  • @esevelos If you have a long-running `async` computation, you could create a `nop` function and call it at convenient cancellation points in your code, e.g., [Can I explicitly check for cancellation / terminate async computation?](http://stackoverflow.com/questions/18676657/can-i-explicitly-check-for-cancellation-terminate-async-computation/18677531#18677531) – Jack P. Oct 09 '13 at 19:14