Tasks and .NET Async
Cold (explicit start) Hot (runs immediately) Better (state machines) F#-centric code, composition ASP.NET Core,.NET library interop
open System.Net.Http
open System.Threading.Tasks
let client = new HttpClient()
let getLength (url: string) : Task<int> = task {
let! body = client.GetStringAsync url
return body.Length
}
let main () = task {
let! lengths =
[ "https://example.com"; "https://dotnet.microsoft.com" ]
|> List.map getLength
|> Task.WhenAll // parallel
for len in lengths do printfn "%d" len
// use! for async disposables, try/with/finally inside tasks
try
use! response = client.GetAsync "https://example.com"
response.EnsureSuccessStatusCode() |> ignore
with ex -> eprintfn "Failed: %s" ex.Message
}
main().Wait()
// ValueTask: backgroundTask { } (runs on the thread pool), valueTask via IcedTasks
// Cancellation: pass CancellationToken explicitly to .NET APIs; IcedTasks provides cancellableTask { }