Global state and Async Workflows in F# -


a common example used illustrate asynchronous workflows in f# retrieving multiple webpages in parallel. 1 such example given at: http://en.wikibooks.org/wiki/f_sharp_programming/async_workflows code shown here in case link changes in future:

open system.text.regularexpressions open system.net  let download url =     let webclient = new system.net.webclient()     webclient.downloadstring(url : string)  let extractlinks html = regex.matches(html, @"http://\s+")  let downloadandextractlinks url =     let links = (url |> download |> extractlinks)     url, links.count  let urls =      [@"http://www.craigslist.com/";      @"http://www.msn.com/";      @"http://en.wikibooks.org/wiki/main_page";      @"http://www.wordpress.com/";      @"http://news.google.com/";]  let pmap f l =     seq { in l -> async { return f } }     |> async.parallel     |> async.run  let testsynchronous() = list.map downloadandextractlinks urls let testasynchronous() = pmap downloadandextractlinks urls  let time msg f =     let stopwatch = system.diagnostics.stopwatch.startnew()     let temp = f()     stopwatch.stop()     printfn "(%f ms) %s: %a" stopwatch.elapsed.totalmilliseconds msg temp  let main() =     printfn "start..."     time "synchronous" testsynchronous     time "asynchronous" testasynchronous     printfn "done."  main() 

what know how 1 should handle changes in global state such loss of network connection? there elegant way this?

one check state of network prior making async.parallel call, state change during execution. assuming 1 wanted pause execution until network available again rather fail, there functional way this?

first of all, there 1 issue example - uses async.parallel run multiple operations in parallel operations not implemented asynchronous, not avoid blocking excessive number of threads in thread pool.

asynchronous. make code asynchronous, download , downloadandextractlinks functions should asynchronous too, can use asyncdownloadstring of webclient:

let asyncdownload url = async {     let webclient = new system.net.webclient()     return! webclient.asyncdownloadstring(system.uri(url : string)) }  let asyncdownloadandextractlinks url = async {     let! html = asyncdownload url     let links = extractlinks html     return url, links.count }  let pmap f l =     seq { in l -> async { return! f } }     |> async.parallel     |> async.runsynchronously 

retrying. now, answer question - there no built-in mechanism handling of errors such network failure, need implement logic yourself. right approach depends on situation. 1 common approach retry operation number of times , throw exception if not succeed e.g. 10 times. can write primitive takes other asynchronous workflow:

let rec asyncretry times op = async {   try     return! op   e ->     if times <= 1 return (reraise e)     else return! asyncretry (times - 1) op } 

then can change main function build workflow retries download 10 times:

let testasynchronous() =    pmap (asyncretry 10 downloadandextractlinks) urls 

shared state. problem async.parallel return once downloads have completed (if there 1 faulty web site, have wait). if want show results come back, need more sophisticated.

one nice way use f# agent - create agent stores results obtained far , can handle 2 messages - 1 adds new result , returns current state. can start multiple async tasks send result agent and, in separate async workflow, can use polling check current status (and e.g. update user interface).

i wrote msdn series agents , two articles developerfusion have plenty of code samples f# agents.


Comments

Popular posts from this blog

java - pagination of xlsx file to XSSFworkbook using apache POI -

Unlimited choices in BASH case statement -

apache - How do I stop my index.php being run twice for every user -