<Query Kind="FSharpProgram" />

// ------------------------------

open System
open System.Diagnostics
open System.Threading

// ------------------------------

let tid () = Thread.CurrentThread.ManagedThreadId

// ------------------------------

let simulatedJob id time =
    async {
        printfn "+++ [%d] Job %d starts" 
            (tid()) id 
       
        let sw = Stopwatch.StartNew ()
        do! Async.Sleep time
        sw.Stop()
       
        let timespan = sw.ElapsedMilliseconds
        printfn "+++ [%d] Job %d ends %d ms" 
            (tid()) id timespan
       
        return id
    }

// ------------------------------

printfn "\r\n... [%d] RunSynchronously 1000" (tid())
let rsync = Async.RunSynchronously (simulatedJob 1000 1000)
printfn "... [%d] async result: %d" (tid()) rsync

// ------------------------------

printfn "\r\n... [%d] StartWithContinuations 1000" (tid())
Async.StartWithContinuations 
    ((simulatedJob 1000 1000), 
    (fun r -> printfn "*** [%d] Success result: %d" (tid()) r), 
    (fun x -> printfn "*** [%d] Exception: %s" (tid()) x.Message), 
    (fun _ -> printfn "*** [%d] Cancelled" (tid())))

// ------------------------------

printfn "\r\n... [%d] StartAsTask 2000" (tid())
let task = Async.StartAsTask (simulatedJob 2000 2000)
printfn "... [%d] Do some other work..." (tid())
let rtask = task.Result // task.Wait()
printfn "... [%d] Task result: %d" (tid()) rtask
                                                          
// ------------------------------

printfn "\r\n... [%d] Parallel" (tid())

let rpar = 
    [3000; 2000; 1000]
        |> List.map (fun time -> 
                    simulatedJob time time)
        |> Async.Parallel
        |> Async.RunSynchronously

printfn "\r\n... [%d] parallel results: %A" (tid()) rpar

// ------------------------------
printfn ""
// ---