Det finns många områden där vi kan använda asynkrona operationer. Exempelvis när vi skriver och läser till fil, anropar WCF tjänster, anropar metoder eller funktioner som tar lång tid, ansluter eller ställer frågor till en databas. Asynkrona arbetsflöden kan ge oss en anmärkningsvärd prestandaförbättring i många av dessa tillfällen. När ett program utför en asynkron operation är det inte lätt att förutse när operationen klar. Om vi inte hanterar de asynkrona anropen ordentligt kan anropet vara ineffektivt eller koden kan sluta svara eller bli blockerad. Att kontrollera dessa problem kan med dagens teknik vara svårt att genomföra eller krångligt att förstå.
I F# har detta till stor del förenklats tack vare Asynchronous workflows. Med F# Asynchronous Workflows kan du skriva asynkrona anrop utan att explecit deklarera callback-metoder. Du skriver koden som om den exekverade synkront. Men den kommer att exekvera asynkront och resultatet av den asynkrona koden kommer att vänta, medan den asynkrona koden körs för att sen fånga upp svaret när det asynkrona anropet är klart.
För att exekvera kod asynkront så skriver du koden i ett async-block och detta block kommer att returnera ett svar av typen Async<’T> vilket ska tolkas som att så småningom kommer det att returneras ett object av ’T. Koden i async -blocket kommer inte att starta förrän ett let! eller ett do! åtgärd görs.
Här är ett kodexempel som hämtar innehållet på en webbsida asynkront:
#r "FSharp.PowerPack.dll"
open System.IO
open System.Net
open Microsoft.FSharp.Control.WebExtensions
let getHTML (url:string) =
async {
let req = WebRequest.Create(url)
let! rsp = req.AsyncGetResponse()
use stream = rsp.GetResponseStream()
use reader = new StreamReader(stream)
return! reader.AsyncReadToEnd()
}
let html = getHTML "http://sv.wikipedia.org/wiki/F_Sharp" |> Async.RunSynchronously
I det här exemplet så hämtas flera webbsidor asynkront och dessutom parallellt:
let webPages : string[] =
[ "http://www.addskills.se"; "http://www.connecta.se"; "http://cs.hubfs.net/" ]
|> List.map getHTML
|> Async.Parallel
|> Async.RunSynchronously
Du kan givetvis anropa funktioner asynkront som i detta exempel:
let task1 = async { return longRunningFunction1 12 34 }
let task2 = async { return longRunningFunction2 56 78 }
let parallelAsyncResult = Async.Parallel [ task1; task2 ]
Programmera med F# och Visual Studio 2010
Vill du lära dig mer om F# så erbjuder Addskills kursen Programmera med F# och Visual Studio 2010. Kursen är en introduktion till F# men innehåller även många avancerade delar av F#. Där får du bland annat en djupare förståelse av Asynchronous Workflows, parallell programmering och mycket mer.
Artikeln är skriven av Hans Sterby, konsult på Connecta och kursledare för Addskills.