<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Luca Bolognese's WebLog : .NET Futures</title><link>http://blogs.msdn.com/lucabol/archive/tags/.NET+Futures/default.aspx</link><description>Tags: .NET Futures</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>My PDC session is online - “Future directions for C# and Visual Basic”</title><link>http://blogs.msdn.com/lucabol/archive/2009/11/23/my-pdc-session-is-online-future-directions-for-c-and-visual-basic.aspx</link><pubDate>Mon, 23 Nov 2009 21:17:44 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9927546</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9927546.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9927546</wfw:commentRss><description>&lt;p&gt;In case you are training to play the part of a first generation Italian immigrant in a Broadway show or if you want to understand why I never short msft stock: &lt;a title="http://microsoftpdc.com/Sessions/FT11" href="http://microsoftpdc.com/Sessions/FT11"&gt;http://microsoftpdc.com/Sessions/FT11&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9927546" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/C_2300_+Programming/default.aspx">C# Programming</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/.NET+Futures/default.aspx">.NET Futures</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/VB/default.aspx">VB</category></item><item><title>Luca at PDC 2009 next week</title><link>http://blogs.msdn.com/lucabol/archive/2009/11/13/luca-at-pdc-2009-next-week.aspx</link><pubDate>Fri, 13 Nov 2009 18:49:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9922139</guid><dc:creator>lucabol</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9922139.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9922139</wfw:commentRss><description>&lt;p&gt;I’ll be in Los Angeles next week for PDC 2009. My session is called “&lt;a href="http://microsoftpdc.com/Sessions/FT11"&gt;Future Directions for C# and Visual Basic&lt;/a&gt;” and it comes on Tuesday immediately after the first keynote.&lt;/p&gt;  &lt;p&gt;I’m planning on spending the first half of the session talking about the biggest trends influencing C# and VB. The second part will be about more future looking features we are playing with these days.&lt;/p&gt;  &lt;p&gt;My deck has just two slides, as always. It’s all about watching me typing code on stage, hoping that I make crazy errors …&lt;/p&gt;  &lt;p&gt;There are several other interesting language related sessions at PDC. Here is a list of them (please notice that the times might change). Also feel free to drop by the languages booth and chat. My team and I will be there most of the time.&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="0"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;&lt;b&gt;Day&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;&lt;b&gt;Time&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Title&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;&lt;b&gt;Presenter&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;&lt;b&gt;Room&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;11:00 - 12:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Future Directions for C# and Visual Basic&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Luca Bolognese&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Hall F&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;11:00 - 12:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Accelerated Windows Application Development with Microsoft Visual C++ 2010&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Boris Jabes&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;408B&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;b&gt;&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:30 - 13:15&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Dynamic Binding in C# 4&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Mads Torgersen&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Hall F&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;b&gt;&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:30 - 13:15&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Using Dynamic Languages to Build Scriptable Applications&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Dino Viehland&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;403AB&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;13:30 - 14:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;C++ Forever: Interactive Applications in the Age of Manycore&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Rick Molloy&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;515B&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;16:30 - 17:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Manycore and the Microsoft .NET Framework 4: A Match Made in Microsoft Visual Studio 2010&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Stephen Toub&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;502A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;16:30 - 17:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Code Contracts and Pex: Power Charge Your Assertions and Unit Tests&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Mike Barnett, Nikolai Tillmann&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;408A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;11:30 - 12:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Microsoft Perspectives on the Future of Programming&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Panel&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall C&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:00 - 13:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;F# for Architects – Hitting the Sweet Spot&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Chris Smith&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;VS and .NET Pavillion&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;13:00 - 13:45&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Code Like the Wind with Microsoft Visual Basic 2010&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Lucian Wischik&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall D&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;13:00 - 13:45&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Future of Garbage Collection&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Patrick Dussud&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall C&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;13:00 - 13:45&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Microsoft Project Code Name “M”: The Data and Modeling Language&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Don Box, Jeff Pinkston&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;408A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;08:30 - 09:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;PLINQ: LINQ, but Faster!&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Ed Essey, Igor Ostrovsky&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;515A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;10:00 - 11:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;A Lap around Microsoft Visual Studio 2010 for the Visual Basic Developer &lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Lisa Feigenbaum&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;VS and .NET Pavillion&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;10:00 - 11:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Axum: A .NET Language for Safe and Scalable Concurrency&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Niklas Gustafsson&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;515A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;11:30 - 12:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;F# for Parallel and Asynchronous Programming&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Luke Hoban&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;515A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:45 - 13:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Microsoft Visual C# IDE Tips and Tricks&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;DJ Park&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall D&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;b&gt;&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:45 - 13:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Microsoft Visual Basic IDE Tips and Tricks&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Dustin Campbell&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall C&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9922139" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/C_2300_+Programming/default.aspx">C# Programming</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/.NET+Futures/default.aspx">.NET Futures</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/VB/default.aspx">VB</category></item><item><title>An Async Html cache – part II – Testing the cache</title><link>http://blogs.msdn.com/lucabol/archive/2009/05/08/an-async-html-cache-part-ii-testing-the-cache.aspx</link><pubDate>Fri, 08 May 2009 18:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9589057</guid><dc:creator>lucabol</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9589057.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9589057</wfw:commentRss><description>&lt;P&gt;Other posts:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2009/04/27/an-async-html-cache-part-i.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2009/04/27/an-async-html-cache-part-i.aspx"&gt;Part I – Writing the cache&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Let’s try out our little cache. First I want to write a synchronous version of it as a baseline.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Private Shared Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;TestSync(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;sites() &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;sitesToDownload &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As Integer&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;howLong &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As Integer&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;syncCache &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Dictionary&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;count = sites.Count()
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;url1 = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"http://moneycentral.msn.com/investor/invsub/results/statemnt.aspx?Symbol="

        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;For &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;i = 0 &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;To &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;sitesToDownload - 1
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;html &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As String &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;= &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;""
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;url = url1 &amp;amp; sites(i &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Mod &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;count)
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;If Not &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;&lt;STRONG&gt;syncCache.TryGetValue(url, html)&lt;/STRONG&gt; &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Then
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;html = LoadWebPage(url)
                &lt;STRONG&gt;syncCache(url) = html&lt;/STRONG&gt;
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End If
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;DoWork(html, howLong)
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Next
    End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;This is a loop that loads webpages in the cache if they are not already there. &lt;EM&gt;sites&lt;/EM&gt; is a list of tickers used to compose the urls; &lt;EM&gt;sitesToDownload&lt;/EM&gt; is the total number of sites to download, so that a single url can be loaded multiple times; &lt;EM&gt;howLong&lt;/EM&gt; represents the work to be done on each loaded page.&lt;/P&gt;
&lt;P&gt;In this version the cache is simply a &lt;EM&gt;Dictionary&lt;/EM&gt; and there is no parallelism. The two bold lines is where the cache is managed.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;DoWork&lt;/EM&gt; is this.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Public Shared Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;DoWork(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;html &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;howLong &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As Integer&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Thread&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Sleep(howLong)
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Let’s take a look at the asynchronous version.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Private Shared Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;TestAsync(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;sites() &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;sitesToDownload &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As Integer&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;howLong &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As Integer&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;htmlCache &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;HtmlCache
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;count = sites.Count()
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;url = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"http://moneycentral.msn.com/investor/invsub/results/statemnt.aspx?Symbol="
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Using &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;ce = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;CountdownEvent&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(sitesToDownload)
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;For &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;i = 1 &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;To &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;sitesToDownload
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;htmlCache&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.GetHtmlAsync(
                    url &amp;amp; sites(i &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Mod &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;count),
                    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Sub&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(s)
                        DoWork(s, howLong)
                        ce.Signal()
                    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Next
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;ce.Wait()
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End Using&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;There are several points worth making on this:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The lambda used as second parameter for &lt;EM&gt;GetHtmlAsync&lt;/EM&gt; is invoked on a different thread whenever the html has been retrieved (which could be immediately if the cache has downloaded the url before) &lt;/LI&gt;
&lt;LI&gt;&lt;EM&gt;CountDownEvent&lt;/EM&gt; allows a thread to wait for a certain number of signals to be sent. The waiting happens on the main thread in the &lt;EM&gt;ce.Wait()&lt;/EM&gt; instruction. The triggering of the event happens in the lambda described in the point above (the &lt;EM&gt;ce.Signal() &lt;/EM&gt;instruction) &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;This is the driver for the overall testing.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Private Shared Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;TestPerf(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;s &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;a &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;iterations &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As Integer&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;clock &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Stopwatch

        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;clock.Start()
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;For &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;i = 1 &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;To &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;iterations
            a()
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Next
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;clock.Stop()
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;ts = clock.Elapsed
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;elapsedTime = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Format(s &amp;amp; &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;": {0:00}:{1:00}:{2:00}.{3:00}"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10)
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.WriteLine(elapsedTime, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"RunTime"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;There is not much to say about it. Start the clock, perform a bunch of iterations of the passed lambda, stop the clock, print out performance.&lt;/P&gt;
&lt;P&gt;And finally the main method. Note that all the adjustable parameters are factored out before the calls to &lt;EM&gt;TestPerf&lt;/EM&gt;.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Public Shared Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Main()
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;tickers = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;New String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;() {&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"mmm"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"aos"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"shlm"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"cas"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"abt"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"anf"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"abm"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"akr"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"acet"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"afl"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"agl"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"adc"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"apd"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;,&lt;BR&gt;                                           &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"ayr"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"alsk"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"ain"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"axb"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"are"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"ale"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"ab"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"all"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;}

        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;sitesToDownload = 50
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;workToDoOnEachUrlInMilliSec = 20
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;perfIterations = 5

        TestPerf(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"Async"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Sub&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;() TestAsync(tickers, sitesToDownload, workToDoOnEachUrlInMilliSec), perfIterations)
        TestPerf(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #a31515"&gt;"Sync"&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Sub&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;() TestSync(tickers, sitesToDownload, workToDoOnEachUrlInMilliSec), perfIterations)
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Feel free to change (&lt;EM&gt;tickers&lt;/EM&gt;, &lt;EM&gt;sitesToDownload&lt;/EM&gt;, &lt;EM&gt;workToDoOnEachUrlInMilliSec&lt;/EM&gt;, &lt;EM&gt;perfIterations&lt;/EM&gt;). Depending on the ratios between these parameters and the number of cores on your machine, you’re going to see different results. Which highlights the fact that parallelizing your algorithms can yield performance gains or not depending on both software and hardware considerations. I get ~3X improvement on my box. I attached the full source file for your amusement. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9589057" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/lucabol/attachment/9589057.ashx" length="4900" type="text/plain" /><category domain="http://blogs.msdn.com/lucabol/archive/tags/.NET+Futures/default.aspx">.NET Futures</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/VB/default.aspx">VB</category></item><item><title>An Async Html cache – Part I - Writing the cache</title><link>http://blogs.msdn.com/lucabol/archive/2009/04/27/an-async-html-cache-part-i.aspx</link><pubDate>Tue, 28 Apr 2009 02:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9572478</guid><dc:creator>lucabol</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9572478.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9572478</wfw:commentRss><description>&lt;P&gt;Other posts:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#006bad&gt;&lt;A href="http://blogs.msdn.com/lucabol/" mce_href="http://blogs.msdn.com/lucabol/"&gt;Part II - Testing the cache&lt;/A&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;In the process of converting a financial VBA Excel Addin to .NET (more on that in later posts), I found myself in dire need of a HTML cache that can be called from multiple threads without blocking them. Visualize it as a glorified dictionary where each entry is (url, cachedHtml). The only difference is that when you get the page, you pass a callback to be invoked when the html has been loaded (which could be immediately if the html had already been retrieved by someone else).&lt;/P&gt;
&lt;P&gt;In essence, I want this:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Public Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;GetHtmlAsync(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;url &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;callback &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;))&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;I’m not a big expert in the &lt;A href="http://msdn.microsoft.com/en-us/concurrency/default.aspx" mce_href="http://msdn.microsoft.com/en-us/concurrency/default.aspx"&gt;.Net Parallel Extensions&lt;/A&gt;, but I’ve got &lt;A href="http://blogs.msdn.com/pfxteam" mce_href="http://blogs.msdn.com/pfxteam"&gt;help&lt;/A&gt;. Stephen Toub helped so much with this that he could have blogged about it himself. And, by the way, this code runs on Visual Studio 2010, which we haven’t shipped yet. I believe with some modifications, it can be run in 2008 + .Net Parallel Extensions CTP, but you’ll have to change a bunch of names.&lt;/P&gt;
&lt;P&gt;In any case, here it comes. First, let’s add some imports.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;Imports &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;System.Collections.Concurrent
&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Imports &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;System.Threading.Tasks
&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Imports &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;System.Threading
&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Imports &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;System.&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #0000a5"&gt;Net&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Then, let’s define an asynchronous cache.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;Public Class &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;AsyncCache&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;TKey, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #0000a5"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;)&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;This thing needs to store the (url, html) pairs somewhere and, luckily enough, there is an handy &lt;EM&gt;ConcurrentDictionary&lt;/EM&gt; that I can use. Also the cache needs to know how to load a &lt;EM&gt;TValue&lt;/EM&gt; given a &lt;EM&gt;TKey&lt;/EM&gt;. In ‘programmingese’, that means.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Private &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_loader &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Func&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TKey&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Private &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;ConcurrentDictionary&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TKey&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;))&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;I’ll need a way to create it.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Public Sub New&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;l &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Func&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TKey&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;))
        _loader = l
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Notice in the above code the use of the &lt;EM&gt;Task&lt;/EM&gt; class for my dictionary instead of &lt;EM&gt;TValue&lt;/EM&gt;. Task is a very good abstraction for “do some work asynchronously and call me when you are done”. It’s easy to initialize and it’s easy to attach callbacks to it. Indeed, this is what we’ll do next:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Public Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;GetValueAsync(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;key &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TKey&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;callback &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;))

        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;task &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;) = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Nothing
        If Not &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryGetValue(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Then
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;task = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Function&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;() _loader(key), &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TaskCreationOptions&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.DetachedFromParent)
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;If &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryAdd(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Then
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Start()
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Else
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Cancel()
                _map.TryGetValue(key, task)
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End If
        End If

        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.ContinueWith(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Sub&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(t) callback(t.Result))
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Wow. Ok, let me explain. This method is divided in two parts. The first part is just a thread safe way to say “give me the task corresponding to this key or, if the task hasn’t been inserted in the cache yet, create it and insert it”. The second part just says “add callback to the list of functions to be called when the task has finished running”.&lt;/P&gt;
&lt;P&gt;The first part needs some more explanation. What is &lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TaskCreationOptions&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.DetachedFromParent? It essentially says that the created task is not going to prevent the parent task from terminating. In essence, the task that created the child task won’t wait for its conclusion. The rest is better explained in comments.&lt;/SPAN&gt;&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;If Not &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryGetValue(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Then &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' Is the task in the cache? (Loc. X)
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;task = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Function&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;() _loader(key), &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TaskCreationOptions&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.DetachedFromParent) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' No, create it
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;If &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryAdd(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Then &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' Try to add it
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Start() &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' I succeeded. I’m the one who added this task. I can safely start it.
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Else
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Cancel() &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' I failed, someone inserted the task after I checked in (Loc. X). Cancel it.
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryGetValue(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' And get the one that someone inserted
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End If
        End If&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Got it? Well, I admit I trust Stephen that this is what I should do …&lt;/P&gt;
&lt;P&gt;I can then create my little HTML Cache by using the above class as in:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;Public Class &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;HtmlCache
&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;
    Public Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;GetHtmlAsync(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;url &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;callback &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Of String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;))
        _asyncCache.GetValueAsync(url, callback)
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;End Sub

    Private Function &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;LoadWebPage(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;url &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As String
        Using &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;client &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;WebClient&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;()
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;'Test.PrintThread("Downloading on thread {0} ...")
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Return &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;client.DownloadString(url)
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;End Using
    End Function

    Private &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;_asyncCache &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;AsyncCache&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Of String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;)(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;AddressOf &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;LoadWebPage)

&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;End Class&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;I have no idea why coloring got disabled when I copy/paste. It doesn’t matter, this is trivial. I just create an &lt;EM&gt;AsyncCache&lt;/EM&gt; and initialize it with a method that knows how to load a web page. I then simply implement &lt;EM&gt;GetHtmlAsync&lt;/EM&gt; by delegating to the underlying &lt;EM&gt;GetValueAsync&lt;/EM&gt; on &lt;EM&gt;AsyncCache&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;It is somehow bizarre to call &lt;EM&gt;Webclient.DownloadString&lt;/EM&gt;, when the design could be revised to take advantage of its asynchronous version. Maybe I’ll do it in another post. Next time, I’ll write code to use this thing.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9572478" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/.NET+Futures/default.aspx">.NET Futures</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/VB/default.aspx">VB</category></item><item><title>Luca presenting F# at PDC 2008</title><link>http://blogs.msdn.com/lucabol/archive/2008/10/24/luca-presenting-f-at-pdc-2008.aspx</link><pubDate>Fri, 24 Oct 2008 19:21:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9014944</guid><dc:creator>lucabol</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9014944.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9014944</wfw:commentRss><description>&lt;p&gt;Next Thursday at 1.45pm I will present &lt;a href="http://channel9.msdn.com/pdc2008/TL11/"&gt;&amp;quot;An introduction to Microsoft F#&amp;quot;&lt;/a&gt; at PDC 2008. If you are there, please stop by or drop by the lounge area to chat.&lt;/p&gt;  &lt;p&gt;There are a bunch of other great sessions from my team. They are all good (I swear I tried to format John's session correctly, but failed).&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;strong&gt;TL16: The Future of C#&lt;/strong&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Speaker: Anders Hejlsberg&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Mon 10/27 | 1:45 PM-3:00 PM | Petree Hall CD&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Repeated: Wed 10/29 | 3:00 PM-4:15 PM | 502A &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;strong&gt;TL10: Deep Dive: Dynamic Languages in .NET&lt;/strong&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Speaker: Jim Hugunin&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Mon 10/27 | 3:30PM | 502A&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;strong&gt;TL11: An Introduction to Microsoft F#&lt;/strong&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Speaker: Luca Bolognese &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Thu 10/30 | 1:45 PM-3:00 PM | 502A &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;strong&gt;TL12: Future Directions for Microsoft Visual Basic&lt;/strong&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Speaker: Paul Vick&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Tue 10/28 | 5:15 PM-6:30 PM | 406A&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;strong&gt;TL54: Natural Interop with Silverlight and Office&lt;/strong&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Alex Turner&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;Tue 10/28 | 12:45 PM-1:30 PM | 404A &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;strong&gt;TL57: A Panel on the Future of Programming Languages&lt;/strong&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;G. Bracha, D.Crockford, A. Hejlsberg, E. Meijer, W.Schulte, J. Siek &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div class="MsoNormal" style="margin-left: 1in; text-indent: -0.25in; mso-list: l0 level2 lfo1; tab-stops: list 1.0in"&gt;&lt;span lang="DE" style="mso-ansi-language: de"&gt;Wed 10/29 | 10:30 AM-11:45 AM | 403AB&lt;/span&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;&lt;strong&gt;TL44 IronRuby: The Right Language for the Right Job&lt;/strong&gt; &lt;/li&gt;      &lt;ul&gt;       &lt;li&gt;l Speaker: John Lam&lt;/li&gt;        &lt;li&gt;l Mon 10/27, 5:15PM, 515B &lt;/li&gt;     &lt;/ul&gt;   &lt;/ul&gt; &lt;/ul&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9014944" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/Miscellanea/default.aspx">Miscellanea</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/.NET+Futures/default.aspx">.NET Futures</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>ObjectSpaces early days ...</title><link>http://blogs.msdn.com/lucabol/archive/2007/06/07/objectspaces-early-days.aspx</link><pubDate>Thu, 07 Jun 2007 17:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3142658</guid><dc:creator>lucabol</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/3142658.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=3142658</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;Matt has &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/mattwar/archive/2007/05/31/the-origin-of-linq-to-sql.aspx"&gt;&lt;FONT face=Tahoma color=#0000ff&gt;a very good post&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma&gt; on the history of object relational framework inside Microsoft. He and I started the whole ObjectSpaces thing together very many years ago (about six and a half). I thought I should add my two cents. &lt;S&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/S&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;You might be wondering how a project starts inside Microsoft (or you might not). In this case, I was hired in the ADO.NET team to build an object relational framework. That was my assignment. The problem was that I had no dev or tester to work with. I also had just arrived in the US from Italy and my English was terrible (that hasn’t changed much). My only qualifications for the job were that I was incredibly passionate about the topic; I had built a couple of small ones in my spare time and have used many more in various projects. But still I had no idea on how to make things happen in this big company. Hell, I could barely understand what people were talking about at lunch.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;Anyhow, my boss told me that there was a guy who was relatively free, but I had to come up with an idea, convince him that the idea was a good one and that he should go ahead and prototype it. That guy was Matt Warren, already one of the best developers in the SQL team and the dev lead of plenty of our .NET stack.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;The first time I entered his office and started talking, he immediately told me: “Not now, I’m debugging”. A good start … But after that, we hit it off immediately. We talked about what an OR framework is, what it should be, how we could innovate in the space and so on. After a while, Matt started working on the very first ObjectSpaces prototype. Our modus operandi was peculiar. I would go to Matt’s office and we would discuss a particular feature or scenario. He would tell me: “Ok, we are on the same page, I’ll see you tomorrow”. The next day the feature would be implemented. If he told me: “It is going to take me 5 days to code it” I knew he didn’t like the feature and I had some more convincing to do. Sometime we would agree, sometime we wouldn’t. Sometime I came up with staff to implement, sometimes Matt did. We figured out a lot of stuff in those days.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;Also I learned how to work with different categories of programmers. If you work with a bad programmer you have to tell him how to implement something. If you work with a good programmer you have to tell him what you want the feature to look like. If you work with an excellent programmer, you just have to tell him what your final goal is. I quickly realized that the latter was the most productive strategy with Matt. I had just to convince him of the business need for something. Implementing it ended up to be a detail.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;That initial prototype grew to become ObjectSpaces (it was called Cheops initially). The team grew to be about 25 people, growing and stretching me personally. We went through two painful rounds of unifications with bigger products. In the end ObjectSpaces was cut. Matt moved to the C# team to work on LINQ. Dinesh and I followed after a short while. The whole ObjectSpaces team scattered in various places around the company. The object relational thing started again in the C# team as part of the LINQ project. This time around we also had a compiler to play with. Plus Anders was on board to sprinkle his design magic over the whole thing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;As &lt;/FONT&gt;&lt;A href="http://en.wikipedia.org/wiki/The_Dark_Tower_(series)"&gt;&lt;FONT face=Tahoma color=#0000ff&gt;Roland&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma&gt; would say, the world has moved on. Matt is now a big shot architect and I lead a team of amazingly smart individuals (they are forced to act as if my words make sense, imagine that …). We are shipping a game changing product in LINQ and a wonderful object relational framework in LINQ to SQL. Things turned out for the best (even if five years too late).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Tahoma&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;Still it is a pleasure to think back at those early days (and nights) of ‘figuring out stuff’ six years ago. A lot of that ‘stuff’ is inside our products today, and that is something to be proud of.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3142658" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/C_2300_+Programming/default.aspx">C# Programming</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/.NET+Futures/default.aspx">.NET Futures</category></item><item><title>My LINQ Overview session at TechEd will be live on the Internet ...</title><link>http://blogs.msdn.com/lucabol/archive/2007/06/04/my-linq-overview-session-at-teched-will-be-live-on-the-internet.aspx</link><pubDate>Mon, 04 Jun 2007 19:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3083518</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/3083518.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=3083518</wfw:commentRss><description>&lt;P&gt;... at least they told me so. It is at 8.30am Eastern time. I don't know the exact link, but it will be somewhere here: &lt;A href="http://www.microsoft.com/events/teched2007/default.mspx" mce_href="http://www.microsoft.com/events/teched2007/default.mspx"&gt;http://www.microsoft.com/events/teched2007/default.mspx&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3083518" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/C_2300_+Programming/default.aspx">C# Programming</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/.NET+Futures/default.aspx">.NET Futures</category></item></channel></rss>