{"id":940,"date":"2009-12-21T18:01:33","date_gmt":"2009-12-21T17:01:33","guid":{"rendered":"http:\/\/www.navision-blog.de\/2009\/12\/21\/observing-asynchronous-downloads-with-f-and-the-reactive-extensions-for-net\/"},"modified":"2022-11-19T13:02:38","modified_gmt":"2022-11-19T13:02:38","slug":"observing-asynchronous-downloads-with-f-and-the-reactive-extensions-for-net","status":"publish","type":"post","link":"http:\/\/www.navision-blog.de\/blog\/2009\/12\/21\/observing-asynchronous-downloads-with-f-and-the-reactive-extensions-for-net\/","title":{"rendered":"Observing asynchronous downloads with F# and the Reactive Extensions for .NET"},"content":{"rendered":"<p>In one of my lasts posts I showed how we can <a href=\"http:\/\/www.navision-blog.de\/2009\/11\/23\/mapping-the-reactive-framework-rx-operators-for-f\/\">transform some of the operators from the Reactive Framework for an easier use in F#<\/a>. This time I will demonstrate how we can use this API and asynchronous workflows to download a couple of websites asynchronous and in parallel.<\/p>\n<p>First of all we create a synchronous download function:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> SyncHttp (url:string) =<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">let<\/span> request = WebRequest.Create url<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">let<\/span> response = request.GetResponse()<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">use<\/span> stream = response.GetResponseStream()<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">use<\/span> reader = <span style=\"color: blue\">new<\/span> StreamReader(stream)<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">let<\/span> result = reader.ReadToEnd()<\/p>\n<p style=\"margin: 0px\">&#160; url,result<\/p>\n<\/p>\n<\/div>\n<p>In F# we can easily make this function asynchronously:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> AsyncHttp (url:string) =<\/p>\n<p style=\"margin: 0px\">&#160; async { <span style=\"color: green\">\/\/ using asynchronous workflows<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> request = WebRequest.Create url<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: green\">\/\/ async call of GetResponse<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">let!<\/span> response = request.AsyncGetResponse()<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">use<\/span> stream = response.GetResponseStream()<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">use<\/span> reader = <span style=\"color: blue\">new<\/span> StreamReader(stream)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: green\">\/\/ async call of ReadToEnd<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">let!<\/span> result = reader.AsyncReadToEnd()<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">return<\/span> url,result}&#160; <\/p>\n<\/p>\n<\/div>\n<p>Now we use this AsyncHttp function to create a list of async downloads:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/ Async&lt;string * string&gt; list<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> downloads =<\/p>\n<p style=\"margin: 0px\">&#160; [<span style=\"color: maroon\">&quot;http:\/\/www.google.com&quot;<\/span>;<\/p>\n<p style=\"margin: 0px\">&#160;&#160; <span style=\"color: maroon\">&quot;http:\/\/www.twitter.com&quot;<\/span>;<\/p>\n<p style=\"margin: 0px\">&#160;&#160; <span style=\"color: maroon\">&quot;http:\/\/www.nytimes.com\/&quot;<\/span>;<\/p>\n<p style=\"margin: 0px\">&#160;&#160; <span style=\"color: maroon\">&quot;http:\/\/www.navision-blog.de\/&quot;<\/span>;<\/p>\n<p style=\"margin: 0px\">&#160;&#160; <span style=\"color: maroon\">&quot;http:\/\/www.nba.com\/&quot;<\/span>]&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; List.map AsyncHttp<\/p>\n<\/p>\n<\/div>\n<p>The next step is to convert the list of async calls into a list of observables and to merge this list into a single IObservable. The effect is that whenever one download is completed we will be notified about the result:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/ IObservable&lt;string * string&gt;<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> observableDownloads =<\/p>\n<p style=\"margin: 0px\">&#160; downloads<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Seq.map Observable.ofAsync<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.merge<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<\/p>\n<\/div>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\">observableDownloads<\/p>\n<p style=\"margin: 0px\">&#160; |&gt; Observable.subscribe (<span style=\"color: blue\">fun<\/span> (url,result) <span style=\"color: blue\">-&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160; printfn <span style=\"color: maroon\">&quot;%A: %d&quot;<\/span> url result.Length)<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<\/p>\n<\/div>\n<p>If you want to learn more about Observable.merge and see the <a href=\"http:\/\/rxwiki.wikidot.com\/marble-diagrams\">marble diagram<\/a> you should watch <a href=\"http:\/\/channel9.msdn.com\/posts\/J.Van.Gogh\/Reactive-Extensions-API-in-depth-Merge\/\">this video<\/a>.<\/p>\n<div style=\"position:absolute; left:-6836px;\"><a href=\"https:\/\/hrvatskaedfarmacija.com\">https:\/\/hrvatskaedfarmacija.com<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>In one of my lasts posts I showed how we can transform some of the operators from the Reactive Framework for an easier use in F#. This time I will demonstrate how we can use this API and asynchronous workflows to download a couple of websites asynchronous and in parallel. First of all we create [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[448],"tags":[664,579,578],"_links":{"self":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/940"}],"collection":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/comments?post=940"}],"version-history":[{"count":3,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/940\/revisions"}],"predecessor-version":[{"id":2015,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/940\/revisions\/2015"}],"wp:attachment":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=940"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=940"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=940"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}