F#:
open System open System.IO open System.Net let getHtml url printStrategy = async { let request = WebRequest.Create(Uri url) use! response = request.AsyncGetResponse() use stream = response.GetResponseStream() use reader = new StreamReader(stream) let contents = reader.ReadToEnd() do printStrategy url contents return contents } let sites = ["http://www.bing.com"; "http://www.google.com"; "http://www.yahoo.com"; "http://msdn.microsoft.com/en-us/fsharp/default.aspx"] let printStrategy url (contents:string) = printfn "%s - HTML Length %d" url contents.Length let sitesHtml = Async.Parallel [for site in sites -> getHtml site printStrategy] |> Async.RunSynchronously do printfn "\r\nProcess Complete\r\nPress any key to continue" do Console.ReadLine() |> ignore
C#:
using System; using System.IO; using System.Net; using System.Threading.Tasks; using System.Linq; namespace CSharpAsync { class Program { static async Task<string> GetHtml(string url, Action<string, string> printStrategy) { var request = WebRequest.Create(new Uri(url)); using (var response = await request.GetResponseAsync()) { using (var stream = response.GetResponseStream()) { using (var reader = new StreamReader(stream)) { var contents = reader.ReadToEnd(); printStrategy.Invoke(url, contents); return contents; } } } } static async Task ProcessSites(string[] sites, Action<string, string> printStrategy) { var sitesHtml = await TaskEx.WhenAll( sites.Select(site => GetHtml(site, printStrategy))); Console.WriteLine("\r\nProcess Complete\r\nPress any key to continue"); } static void Main(string[] args) { var sites = new[] { "http://www.bing.com", "http://www.google.com", "http://www.yahoo.com", "http://msdn.microsoft.com/en-us/fsharp/default.aspx" }; Action<string, string> printStrategy = (url, contents) => Console.WriteLine("{0} - HTML Length {1}", url, contents.Length); ProcessSites(sites, printStrategy).Wait(); Console.ReadLine(); } } }
VB:
Imports System Imports System.IO Imports System.Net Imports System.Threading.Tasks Imports System.Linq Module Module1 Async Function GetHtml(ByVal url As String, ByVal printStrategy As Action(Of String, String)) As Task(Of String) Dim request = WebRequest.Create(New Uri(url)) Using response = Await request.GetResponseAsync() Using stream = response.GetResponseStream() Using reader = New StreamReader(stream) Dim contents = reader.ReadToEnd() printStrategy.Invoke(url, contents) Return contents End Using End Using End Using End Function Async Function ProcessSites(ByVal sites As String(), ByVal printStrategy As Action(Of String, String)) As Task Dim sitesHtml = _ Await TaskEx.WhenAll(sites.Select(Function(site) GetHtml(site, printStrategy))) Console.WriteLine("{0}Process Complete{0}Press any key to continue", _ Environment.NewLine) End Function Sub Main() Dim sites = New String() {"http://www.bing.com", _ "http://www.google.com", _ "http://www.yahoo.com", _ "http://msdn.microsoft.com/en-us/fsharp/default.aspx"} Dim printStrategy As Action(Of String, String) = _ Sub(url, contents) Console.WriteLine("{0} - HTML Length {1}", url, contents.Length) ProcessSites(sites, printStrategy).Wait() Console.ReadLine() End Sub End Module
Hey thanks for the code-snippets, it shows a nice side-by-side comparison of the different languages.
ReplyDeleteThough your C# could be cleaner if you didn't use nested using blocks (i.e. remove braces from the top two using statements). Also I'm not sure why you created an extra method for 'ProcessSites()' instead of having it in-line like the F# version?
Also I might be mistaken but I think you have an extra Wait on 'ProcessSites(sites, printStrategy).Wait();' as it looks like 'var sitesHtml = await TaskEx.WhenAll' already accomplishes this?
- Demis
Thanks for your comments. You make a good point about the removal of the unnecessary braces from the top two using statements. The addition of the braces is an old habit of mine that stems from the coding standards of a company for which I use to work. I should definitely retire that habit.
ReplyDeleteTomas's post (http://tomasp.net/blog/csharp-fsharp-async-intro.aspx) goes into detail about the reasons for the extra method and the extra Wait call.
Hey thanks for the code-snippets, it shows a nice side-by-side comparison of the different languages.
ReplyDeleteThough your C# could be cleaner if you didn't use nested using blocks (i.e. remove braces from the top two using statements). Also I'm not sure why you created an extra method for 'ProcessSites()' instead of having it in-line like the F# version?
Also I might be mistaken but I think you have an extra Wait on 'ProcessSites(sites, printStrategy).Wait();' as it looks like 'var sitesHtml = await TaskEx.WhenAll' already accomplishes this?
- Demis