Async.StartWithContinuations
do! Async.SwitchToThreadPool()
mainAsync
CancelKeyPress
let mainAsync() =
async {
do! Async.SwitchToThreadPool()
use precious = { new System.IDisposable with override this.Dispose() = printfn "safe haven" }
// blow up on purpose after a number of seconds
let seconds = 10
printfn "%d seconds and counting" seconds
do! (System.TimeSpan.FromSeconds(float seconds)).TotalMilliseconds |> int |> Async.Sleep
failwithf "kaboom!"
// the real app is has a System.TimeoutException being thrown from a C# Task
//wcfClient.RetrieveServiceContentAsync someValue |> Async.AwaitTask
}
[<EntryPoint>]
let main argv =
let mutable exitCode = 0
use cancelMainAsync = new System.Threading.CancellationTokenSource()
use cancelMain = new System.Threading.ManualResetEventSlim()
let cancel() =
if not cancelMainAsync.IsCancellationRequested then
cancelMainAsync.Cancel()
cancelMain.Set()
let exceptionHandler (ex: System.Exception) =
let ex =
match ex with
| :? System.AggregateException as ae ->
if ae.InnerExceptions.Count = 1 then ae.InnerException else ex
| _ -> ex
printfn "%A" ex
exitCode <- 1
cancel()
System.Runtime.Loader.AssemblyLoadContext.Default.add_Unloading(fun _ -> cancel())
System.Console.CancelKeyPress.Add (fun args -> args.Cancel <- true; exitCode <- 2; cancel())
Async.StartWithContinuations(mainAsync(), (fun _ -> ()), exceptionHandler, (fun _ -> ()), cancelMainAsync.Token)
cancelMain.Wait()
exitCode
Async.RunSchronously
CancellationToken
OperationCancelException
open System
let mainAsync() =
async {
use precious = { new System.IDisposable with override this.Dispose() = printfn "safe haven" }
// blow up on purpose after a number of seconds
let seconds = 10
printfn "%d seconds and counting" seconds
do! (System.TimeSpan.FromSeconds(float seconds)).TotalMilliseconds |> int |> Async.Sleep
failwithf "kaboom!"
// the real app is has a System.TimeoutException being thrown from a C# Task
//wcfClient.RetrieveServiceContentAsync someValue |> Async.AwaitTask
return 0
}
[<EntryPoint>]
let main argv =
let cancellation = new Threading.CancellationTokenSource()
let cancel() =
if not cancellation.IsCancellationRequested then
cancellation.Cancel()
Runtime.Loader.AssemblyLoadContext.Default.add_Unloading(fun _ -> cancel())
Console.CancelKeyPress.Add (fun event -> event.Cancel <- true; cancel())
Async.RunSynchronously(mainAsync(), cancellationToken = cancellation.Token)
open System
let mainAsync() =
async {
use precious = { new System.IDisposable with override this.Dispose() = printfn "safe haven" }
// blow up on purpose after a number of seconds
let seconds = 10
printfn "%d seconds and counting" seconds
do! (System.TimeSpan.FromSeconds(float seconds)).TotalMilliseconds |> int |> Async.Sleep
failwithf "kaboom!"
// the real app is has a System.TimeoutException being thrown from a C# Task
//wcfClient.RetrieveServiceContentAsync someValue |> Async.AwaitTask
return 0
}
[<EntryPoint>]
let main argv =
let cancellation = new Threading.CancellationTokenSource()
let cancel() =
if not cancellation.IsCancellationRequested then
cancellation.Cancel()
Runtime.Loader.AssemblyLoadContext.Default.add_Unloading(fun _ -> cancel())
Console.CancelKeyPress.Add (fun event -> event.Cancel <- true; cancel())
try
Async.RunSynchronously(mainAsync(), cancellationToken = cancellation.Token)
with
| :? OperationCanceledException -> 2
| ex ->
let ex =
match ex with
| :? AggregateException as ae ->
if ae.InnerExceptions.Count = 1 then ae.InnerException else ex
| _ -> ex
printfn "%A" ex
1