A few months ago I wrote some code that really made me appreciate the new language feature in C#: Anonymous Methods. I decided to turn it into a sample application that creates a web request to www.google.com and downloads it when you push a button... asynchronously (that means the UI does not hang while the application is downloading). Prior to C# 2.0, doing a web request and download the content asynchronously was several hundred lines of sloppy spaghetti code: you need to implement callbacks, cleanup, error handling, state maintenance, etc. A lot of developers, myself included, would “cheat” and wrap synchronous calls in a thread to fake asynchronous requests (this is not ideal for performance).
The beauty of anonymous methods is that the compiler’s syntactic sugar handles a lot of the aforementioned for the developer very elegantly in the background.
Here’s what a fully asynchronous download looks like now, with error handling and cleanup and all (5 anonymous methods in total):
HttpWebRequest req = WebRequest.Create("http://www.google.com") as HttpWebRequest; MemoryStream memStream = new MemoryStream(); HttpWebResponse resp = null; // anonymous method to handle cleanup EventHandler Cleanup = (s, ev) => { using (resp) { } resp = null; using (memStream) { } memStream = null; }; // anonymous method to handle errors EventHandler Error = (s, ev) => { MessageBox.Show((s as Exception).Message); Cleanup(null, null); }; req.BeginGetResponse(responseResult => { // anonymous method that waits for a response from the web server Thread.Sleep(1000); // for asynchronous testing try { resp = req.EndGetResponse(responseResult) as HttpWebResponse; Stream responseStream = resp.GetResponseStream(); byte[] buffer = new byte[1024]; AsyncCallback rc = null; rc = readResult => { // anonymous method that waits to read a some data from the web server Thread.Sleep(1000); // for asynchronous testing try { int read = responseStream.EndRead(readResult); if (read > 0) { memStream.Write(buffer, 0, read); responseStream.BeginRead(buffer, 0, buffer.Length, rc, null); } else { // We finished downloading! Invoke the UI thread to print the data! // anonymous method to handle completion EventHandler Done = (s, ev) => { memStream.Seek(0, SeekOrigin.Begin); string blob = new StreamReader(memStream).ReadToEnd(); Cleanup(null, null); MessageBox.Show(blob); }; Invoke(Done); } } catch (Exception ex) { Invoke(Error, ex); } }; responseStream.BeginRead(buffer, 0, buffer.Length, rc, null); } catch (Exception ex) { Invoke(Error, ex); } }, null);
1 comments:
Thanks for helpful review! For business solutions it is the right way to get outsourcing software development services.
Post a Comment