<?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</title><link>http://blogs.msdn.com/lucabol/default.aspx</link><description>    x += x++;</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><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>0</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>Becoming really rich with C#</title><link>http://blogs.msdn.com/lucabol/archive/2009/09/22/becoming-really-rich-with-c.aspx</link><pubDate>Wed, 23 Sep 2009 02:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9896982</guid><dc:creator>lucabol</dc:creator><slash:comments>13</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9896982.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9896982</wfw:commentRss><description>&lt;P&gt;Or maybe not, please do not hold me responsible if you lose money following this system. Having said that, it is my opinion that there are very few concepts that are important in investing. Three big ones are value, diversification and momentum. This post is about the latter two and how to use C# to create a simple trading system that uses both.&lt;/P&gt;
&lt;P&gt;Diversification is ‘not put all your eggs in one basket’ (contrary to ‘put all of them in one basket and watch that basket’). I don’t believe you can ‘watch’ very much in financial markets, so I tend to prefer diversification.&lt;/P&gt;
&lt;P&gt;Momentum is a mysterious tendency of financial prices that have risen the most in the recent past, to continue outperforming in the close future. In essence, buying the top stocks/sectors/asset classes tends to outperform buying the bottom ones over horizons from three months to one year.&lt;/P&gt;
&lt;P&gt;The idea then is to rank some assets (i.e. ETFs) by how fast they have risen in the past, go long the top ones and short the bottom ones. There are hundreds of variations of this basic strategy, we’ll add the rule that we won’t buy assets that are below their 200 days moving average or sell short assets that are above it.&lt;/P&gt;
&lt;P&gt;I’m writing this code with VS 2010 Beta 2 (which hasn’t shipped yet). It should be trivial to modify it to run on B1 (or maybe it does run on it already). I attach the code and data files to this post.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;struct &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Event &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;internal &lt;/SPAN&gt;Event(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime &lt;/SPAN&gt;date, &lt;SPAN style="COLOR: blue"&gt;double &lt;/SPAN&gt;price) { Date = date; Price = price; }
    &lt;SPAN style="COLOR: blue"&gt;internal readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DateTime &lt;/SPAN&gt;Date;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly double &lt;/SPAN&gt;Price;
}&lt;/PRE&gt;
&lt;P&gt;We’ll use this simple structure to load the closing price for a particular date. My use of internal is kind of bizarre. Actually the whole code might look strange. It is an interesting (maybe un-elegant) mix of object orientation and functional programming.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Summary &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;internal &lt;/SPAN&gt;Summary(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;ticker, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;name, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;assetClass,
                    &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;assetSubClass, &lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;? weekly, &lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;? fourWeeks,
                    &lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;? threeMonths, &lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;? sixMonths, &lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;? oneYear,
                    &lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;? stdDev, &lt;SPAN style="COLOR: blue"&gt;double &lt;/SPAN&gt;price, &lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;? mav200) {
        Ticker = ticker;
        Name = name;
        AssetClass = assetClass;
        AssetSubClass = assetSubClass;
        &lt;SPAN style="COLOR: green"&gt;// Abracadabra ...
        &lt;/SPAN&gt;LRS = (fourWeeks + threeMonths + sixMonths + oneYear) / &lt;SPAN style="COLOR: brown"&gt;4&lt;/SPAN&gt;;
        Weekly = weekly;
        FourWeeks = fourWeeks;
        ThreeMonths = threeMonths;
        SixMonths = sixMonths;
        OneYear = oneYear;
        StdDev = stdDev;
        Mav200 = mav200;
        Price = price;
    }
    &lt;SPAN style="COLOR: blue"&gt;internal readonly string &lt;/SPAN&gt;Ticker;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly string &lt;/SPAN&gt;Name;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly string &lt;/SPAN&gt;AssetClass;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly string &lt;/SPAN&gt;AssetSubClass;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly double&lt;/SPAN&gt;? LRS;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly double&lt;/SPAN&gt;? Weekly;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly double&lt;/SPAN&gt;? FourWeeks;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly double&lt;/SPAN&gt;? ThreeMonths;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly double&lt;/SPAN&gt;? SixMonths;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly double&lt;/SPAN&gt;? OneYear;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly double&lt;/SPAN&gt;? StdDev;
    &lt;SPAN style="COLOR: blue"&gt;internal readonly double&lt;/SPAN&gt;? Mav200;
    &lt;SPAN style="COLOR: blue"&gt;internal double &lt;/SPAN&gt;Price;

    &lt;SPAN style="COLOR: blue"&gt;internal static void &lt;/SPAN&gt;Banner() {
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,-6}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Ticker"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,-50}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Name"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,-12}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Asset Class"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: green"&gt;//Console.Write("{0,-30}\t", "Asset SubClass";
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"RS"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"1Wk"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"4Wk"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"3Ms"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"6Ms"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"1Yr"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,6}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Vol"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"{0,2}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Mv"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: green"&gt;//Console.Write("{0,6}", "Pr");
        //Console.WriteLine("{0,6}", "M200");
    &lt;/SPAN&gt;}

    &lt;SPAN style="COLOR: blue"&gt;internal void &lt;/SPAN&gt;Print() {

        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,-6}"&lt;/SPAN&gt;, Ticker);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,-50}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;String&lt;/SPAN&gt;(Name.Take(&lt;SPAN style="COLOR: brown"&gt;48&lt;/SPAN&gt;).ToArray()));
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,-12}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;String&lt;/SPAN&gt;(AssetClass.Take(&lt;SPAN style="COLOR: brown"&gt;10&lt;/SPAN&gt;).ToArray()));
        &lt;SPAN style="COLOR: green"&gt;//Console.Write("{0,-30}\t", new String(AssetSubClass.Take(28).ToArray()));
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4:N0}"&lt;/SPAN&gt;, LRS * &lt;SPAN style="COLOR: brown"&gt;100&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4:N0}"&lt;/SPAN&gt;, Weekly * &lt;SPAN style="COLOR: brown"&gt;100&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4:N0}"&lt;/SPAN&gt;, FourWeeks * &lt;SPAN style="COLOR: brown"&gt;100&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4:N0}"&lt;/SPAN&gt;, ThreeMonths * &lt;SPAN style="COLOR: brown"&gt;100&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4:N0}"&lt;/SPAN&gt;, SixMonths * &lt;SPAN style="COLOR: brown"&gt;100&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,4:N0}"&lt;/SPAN&gt;, OneYear * &lt;SPAN style="COLOR: brown"&gt;100&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0,6:N0}"&lt;/SPAN&gt;, StdDev * &lt;SPAN style="COLOR: brown"&gt;100&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(Price &amp;lt;= Mav200)
            &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"{0,2}"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"X"&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: blue"&gt;else
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine();
        &lt;SPAN style="COLOR: green"&gt;//Console.Write("{0,6:N2}", Price);
        //Console.WriteLine("{0,6:N2}", Mav200);
    &lt;/SPAN&gt;}
}&lt;/PRE&gt;
&lt;P&gt;The class Summary above is how I want to present my results. A few comments on the code. I use &lt;EM&gt;Nullable&amp;lt;T&amp;gt;&lt;/EM&gt; because some of this values can be null (i.e. not enough history), but I still don’t want to worry about it. It ends up working rather neatly.&lt;/P&gt;
&lt;P&gt;I also print the results out to &lt;EM&gt;Console, &lt;/EM&gt;which is crazy. I really should be using WPF/Silverlight as the presentation layer. Also the &lt;EM&gt;{0,4:N0}&lt;/EM&gt; notation might be unfamiliar to some of you, but this is how mad &lt;EM&gt;Console&lt;/EM&gt; guys like myself avoid using real UI frameworks. Sometimes we print things in color too.&lt;/P&gt;
&lt;P&gt;The real meat is in the following line:&lt;/P&gt;&lt;PRE class=code&gt;LRS = (fourWeeks + threeMonths + sixMonths + oneYear) / &lt;SPAN style="COLOR: brown"&gt;4&lt;/SPAN&gt;;&lt;/PRE&gt;
&lt;P&gt;That is our highway to richness. It’s a very elaborated quant formula, never before shown, that calculate a magick relative strength (aka momentum) factor as the average of the performance of four weeks, three months, six months and one year.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TimeSeries &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;internal readonly string &lt;/SPAN&gt;Ticker;
    &lt;SPAN style="COLOR: blue"&gt;readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DateTime &lt;/SPAN&gt;_start;
    &lt;SPAN style="COLOR: blue"&gt;readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Dictionary&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;&amp;gt; _adjDictionary;
    &lt;SPAN style="COLOR: blue"&gt;readonly string &lt;/SPAN&gt;_name;
    &lt;SPAN style="COLOR: blue"&gt;readonly string &lt;/SPAN&gt;_assetClass;
    &lt;SPAN style="COLOR: blue"&gt;readonly string &lt;/SPAN&gt;_assetSubClass;

    &lt;SPAN style="COLOR: blue"&gt;internal &lt;/SPAN&gt;TimeSeries(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;ticker, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;name, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;assetClass, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;assetSubClass, &lt;BR&gt;                                                                &lt;SPAN style="COLOR: #2b91af"&gt;IEnumerable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Event&lt;/SPAN&gt;&amp;gt; events) {
        Ticker = ticker;
        _name = name;
        _assetClass = assetClass;
        _assetSubClass = assetSubClass;
        _start = events.Last().Date;
        _adjDictionary = events.ToDictionary(e =&amp;gt; e.Date, e =&amp;gt; e.Price);
    }&lt;/PRE&gt;
&lt;P&gt;I then built myself a little TimeSeries class that represents a series of (date, price). I choose a dictionary to store it because of my assumption that I will be accessing it by date a lot. In retrospect, I was kind of right and kind of wrong. It doesn’t really matter much.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;bool &lt;/SPAN&gt;GetPrice(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime &lt;/SPAN&gt;when, &lt;SPAN style="COLOR: blue"&gt;out double &lt;/SPAN&gt;price, &lt;SPAN style="COLOR: blue"&gt;out double &lt;/SPAN&gt;shift) {
    &lt;SPAN style="COLOR: green"&gt;// To nullify the effect of hours/min/sec/millisec being different from 0
    &lt;/SPAN&gt;when = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;(when.Year, when.Month, when.Day);
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;found = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;;
    shift = &lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;double &lt;/SPAN&gt;aPrice = &lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;while &lt;/SPAN&gt;(when &amp;gt;= _start &amp;amp;&amp;amp; !found) {
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(_adjDictionary.TryGetValue(when, &lt;SPAN style="COLOR: blue"&gt;out &lt;/SPAN&gt;aPrice)) {
            found = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;;
        }
        when = when.AddDays(-&lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;);
        shift -= &lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;;
    }
    price = aPrice;
    &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;found;
}&lt;/PRE&gt;
&lt;P&gt;A TimeSeries can give you back the price at a particular date. This looks bizarre and complex, but there is a reason for it. I might ask for a date that doesn’t have a price associated with it (i.e. holidays, week-ends). In such cases I want to return the previous price which could be N days in the past.&lt;/P&gt;
&lt;P&gt;I also want to return how many days in the past I had to go, so that other calculations (i.e. &lt;EM&gt;Return&lt;/EM&gt;) can modify their end date by the same amount. Also I might not find such a price at all, in which case I don’t want to throw an exception, but instead notify the caller. In retrospect, I should have used &lt;EM&gt;double?&lt;/EM&gt; to signify ‘price not found’.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;? GetReturn(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime &lt;/SPAN&gt;start, &lt;SPAN style="COLOR: #2b91af"&gt;DateTime &lt;/SPAN&gt;end) {
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;startPrice = &lt;SPAN style="COLOR: brown"&gt;0.0&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;endPrice = &lt;SPAN style="COLOR: brown"&gt;0.0&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;shift = &lt;SPAN style="COLOR: brown"&gt;0.0&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;foundEnd = GetPrice(end, &lt;SPAN style="COLOR: blue"&gt;out &lt;/SPAN&gt;endPrice, &lt;SPAN style="COLOR: blue"&gt;out &lt;/SPAN&gt;shift);
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;foundStart = GetPrice(start.AddDays(shift), &lt;SPAN style="COLOR: blue"&gt;out &lt;/SPAN&gt;startPrice, &lt;SPAN style="COLOR: blue"&gt;out &lt;/SPAN&gt;shift);
    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(!foundStart || !foundEnd)
        &lt;SPAN style="COLOR: blue"&gt;return null&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;else
        return &lt;/SPAN&gt;endPrice / startPrice - &lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;;
}&lt;/PRE&gt;
&lt;P&gt;We can now go and calculate the return between two dates. Also the &lt;EM&gt;TimeSeries&lt;/EM&gt; object needs to perform a little more calculations.&lt;/P&gt;&lt;PRE class=code&gt;    &lt;SPAN style="COLOR: blue"&gt;internal double&lt;/SPAN&gt;? LastWeekReturn() {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;GetReturn(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now.AddDays(-&lt;SPAN style="COLOR: brown"&gt;7&lt;/SPAN&gt;), &lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now);
    }
    &lt;SPAN style="COLOR: blue"&gt;internal double&lt;/SPAN&gt;? Last4WeeksReturn() {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;GetReturn(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now.AddDays(-&lt;SPAN style="COLOR: brown"&gt;28&lt;/SPAN&gt;), &lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now);
    }
    &lt;SPAN style="COLOR: blue"&gt;internal double&lt;/SPAN&gt;? Last3MonthsReturn() {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;GetReturn(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now.AddMonths(-&lt;SPAN style="COLOR: brown"&gt;3&lt;/SPAN&gt;), &lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now);
    }
    &lt;SPAN style="COLOR: blue"&gt;internal double&lt;/SPAN&gt;? Last6MonthsReturn() {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;GetReturn(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now.AddMonths(-&lt;SPAN style="COLOR: brown"&gt;6&lt;/SPAN&gt;), &lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now);
    }
    &lt;SPAN style="COLOR: blue"&gt;internal double&lt;/SPAN&gt;? LastYearReturn() {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;GetReturn(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now.AddYears(-&lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;), &lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now);
    }
    &lt;SPAN style="COLOR: blue"&gt;internal double&lt;/SPAN&gt;? StdDev() {
        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;now = &lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now;
        now = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;(now.Year, now.Month, now.Day);
        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;limit = now.AddYears(-&lt;SPAN style="COLOR: brown"&gt;3&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;rets = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;&amp;gt;();
        &lt;SPAN style="COLOR: blue"&gt;while &lt;/SPAN&gt;(now &amp;gt;= _start.AddDays(&lt;SPAN style="COLOR: brown"&gt;12&lt;/SPAN&gt;) &amp;amp;&amp;amp; now &amp;gt;= limit) {
            &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;ret = GetReturn(now.AddDays(-&lt;SPAN style="COLOR: brown"&gt;7&lt;/SPAN&gt;), now);
            rets.Add(ret.Value);
            now = now.AddDays(-&lt;SPAN style="COLOR: brown"&gt;7&lt;/SPAN&gt;);
        }
        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;mean = rets.Average();
        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;variance = rets.Select(r =&amp;gt; &lt;SPAN style="COLOR: #2b91af"&gt;Math&lt;/SPAN&gt;.Pow(r - mean, &lt;SPAN style="COLOR: brown"&gt;2&lt;/SPAN&gt;)).Sum();
        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;weeklyStdDev = &lt;SPAN style="COLOR: #2b91af"&gt;Math&lt;/SPAN&gt;.Sqrt(variance / rets.Count);
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;weeklyStdDev * &lt;SPAN style="COLOR: #2b91af"&gt;Math&lt;/SPAN&gt;.Sqrt(&lt;SPAN style="COLOR: brown"&gt;40&lt;/SPAN&gt;);
    }
    &lt;SPAN style="COLOR: blue"&gt;internal double&lt;/SPAN&gt;? MAV200() {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;_adjDictionary&lt;BR&gt;               .ToList()&lt;BR&gt;               .OrderByDescending(k =&amp;gt; k.Key)&lt;BR&gt;               .Take(&lt;SPAN style="COLOR: brown"&gt;200)&lt;BR&gt;               &lt;/SPAN&gt;.Average(k =&amp;gt; k.Value);
    }
    &lt;SPAN style="COLOR: blue"&gt;internal double &lt;/SPAN&gt;TodayPrice() {
        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;price = &lt;SPAN style="COLOR: brown"&gt;0.0&lt;/SPAN&gt;;
        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;shift = &lt;SPAN style="COLOR: brown"&gt;0.0&lt;/SPAN&gt;;
        GetPrice(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now, &lt;SPAN style="COLOR: blue"&gt;out &lt;/SPAN&gt;price, &lt;SPAN style="COLOR: blue"&gt;out &lt;/SPAN&gt;shift);
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;price;
    }
    &lt;SPAN style="COLOR: blue"&gt;internal &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Summary &lt;/SPAN&gt;GetSummary() {
        &lt;SPAN style="COLOR: blue"&gt;return new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Summary&lt;/SPAN&gt;(Ticker, _name, _assetClass, _assetSubClass, &lt;BR&gt;                           LastWeekReturn(), Last4WeeksReturn(), Last3MonthsReturn(),&lt;BR&gt;                           Last6MonthsReturn(), LastYearReturn(), StdDev(), TodayPrice(),&lt;BR&gt;                           MAV200());
    }
}&lt;/PRE&gt;
&lt;P&gt;Nothing particularly interesting in this code. Just a bunch of calculations. The &lt;EM&gt;MAV200&lt;/EM&gt; is the 200 days moving average of closing prices. It shows a more functional way of doing things. The &lt;EM&gt;StdDev&lt;/EM&gt; function is instead very imperative.&lt;/P&gt;
&lt;P&gt;We now can work on downloading the prices. This is how you construct the right URL:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;static string &lt;/SPAN&gt;CreateUrl(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;ticker, &lt;SPAN style="COLOR: #2b91af"&gt;DateTime &lt;/SPAN&gt;start, &lt;SPAN style="COLOR: #2b91af"&gt;DateTime &lt;/SPAN&gt;end) {
    &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;@"http://ichart.finance.yahoo.com/table.csv?s=" &lt;/SPAN&gt;+ ticker + &lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;a="&lt;BR&gt;            &lt;/SPAN&gt;+ (start.Month - &lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;).ToString() + &lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;b=" &lt;/SPAN&gt;+ start.Day.ToString() + &lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;c="&lt;BR&gt;            &lt;/SPAN&gt;+ start.Year.ToString() + &lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;d=" &lt;/SPAN&gt;+ (end.Month - &lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;).ToString() + &lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;e="&lt;BR&gt;            &lt;/SPAN&gt;+ end.Day.ToString() + &lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;f=" &lt;/SPAN&gt;+ end.Year.ToString() + &lt;SPAN style="COLOR: #a31515"&gt;"&amp;amp;g=d&amp;amp;ignore=.csv"&lt;/SPAN&gt;;
}&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And let’s set how many concurrent connections we are going to use …&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ServicePointManager&lt;/SPAN&gt;.DefaultConnectionLimit = &lt;SPAN style="COLOR: brown"&gt;10&lt;/SPAN&gt;;&lt;/PRE&gt;
&lt;P&gt;On my machine, setting this number too high causes errors to be returned. I’m not sure on which side of the connection the problem lies.&lt;/P&gt;
&lt;P&gt;We can then load all the tickers we want to load from a file. One of the files has Leveraged ETFs, which I want to filter out because they tend to pop up always at the top.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;tickers =
    &lt;SPAN style="COLOR: green"&gt;//File.ReadAllLines("ETFs.csv")
    //File.ReadAllLines("ETFTest.csv")
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;File&lt;/SPAN&gt;.ReadAllLines(&lt;SPAN style="COLOR: #a31515"&gt;"AssetClasses.csv"&lt;/SPAN&gt;)
    .Skip(&lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;)
    .Select(l =&amp;gt; l.Split(&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;[] { &lt;SPAN style="COLOR: #a31515"&gt;',' &lt;/SPAN&gt;}))
    .Where(v =&amp;gt; v[&lt;SPAN style="COLOR: brown"&gt;2&lt;/SPAN&gt;] != &lt;SPAN style="COLOR: #a31515"&gt;"Leveraged"&lt;/SPAN&gt;)
    .Select(values =&amp;gt; &lt;SPAN style="COLOR: #2b91af"&gt;Tuple&lt;/SPAN&gt;.Create(values[&lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;], values[&lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;], values[&lt;SPAN style="COLOR: brown"&gt;2&lt;/SPAN&gt;], values[&lt;SPAN style="COLOR: brown"&gt;3&lt;/SPAN&gt;]))
    .ToArray();
&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;len = tickers.Length;

&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;start = &lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now.AddYears(-&lt;SPAN style="COLOR: brown"&gt;2&lt;/SPAN&gt;);
&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;end = &lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now;
&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;cevent = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;CountdownEvent&lt;/SPAN&gt;(len);
&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;summaries = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Summary&lt;/SPAN&gt;[len];&lt;/PRE&gt;
&lt;P&gt;And then load all of them, making sure to make an asynchronous call so not to keep the thread busy.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: #2b91af"&gt;for(var i = &lt;/SPAN&gt;&lt;SPAN style="COLOR: brown"&gt;0;&lt;/SPAN&gt; i &amp;lt; len; i++)  {
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;t = tickers[i];
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;url = CreateUrl(t.Item1, start, end);
    &lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;webClient = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;WebClient&lt;/SPAN&gt;()) {
        webClient.DownloadStringCompleted +=&lt;BR&gt;                          &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DownloadStringCompletedEventHandler&lt;/SPAN&gt;(downloadStringCompleted);
        webClient.DownloadStringAsync(&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri&lt;/SPAN&gt;(url), &lt;SPAN style="COLOR: #2b91af"&gt;Tuple&lt;/SPAN&gt;.Create(t, cevent, summaries, i));
    }
}

cevent.Wait();&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Notice the use of a Countdown event to wait for all the thread to complete before printing out the results. Also notice the new &lt;EM&gt;Tuple&amp;lt;T&amp;gt;&lt;/EM&gt; class used to package things to send around.&lt;/P&gt;
&lt;P&gt;We can then print out the top and bottom 15%:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;top15perc =
        summaries
        .Where(s =&amp;gt; s.LRS.HasValue)
        .OrderByDescending(s =&amp;gt; s.LRS)
        .Take((&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;)(len * &lt;SPAN style="COLOR: brown"&gt;0.15&lt;/SPAN&gt;));
&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;bottom15perc =
        summaries
        .Where(s =&amp;gt; s.LRS.HasValue)
        .OrderBy(s =&amp;gt; s.LRS)
        .Take((&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;)(len * &lt;SPAN style="COLOR: brown"&gt;0.15&lt;/SPAN&gt;));

&lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine();
&lt;SPAN style="COLOR: #2b91af"&gt;Summary&lt;/SPAN&gt;.Banner();
&lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"TOP 15%"&lt;/SPAN&gt;);
&lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;s &lt;SPAN style="COLOR: blue"&gt;in &lt;/SPAN&gt;top15perc)
    s.Print();

&lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine();
&lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"Bottom 15%"&lt;/SPAN&gt;);
&lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;s &lt;SPAN style="COLOR: blue"&gt;in &lt;/SPAN&gt;bottom15perc)
    s.Print();&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here is what we do when a request comes back with data:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;static void &lt;/SPAN&gt;downloadStringCompleted(&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;sender, &lt;SPAN style="COLOR: #2b91af"&gt;DownloadStringCompletedEventArgs &lt;/SPAN&gt;e) {
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;bigTuple =&lt;BR&gt;             (&lt;SPAN style="COLOR: #2b91af"&gt;Tuple&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Tuple&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;gt;, &lt;SPAN style="COLOR: #2b91af"&gt;CountdownEvent&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;Summary&lt;/SPAN&gt;[], &lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;&amp;gt;)&lt;BR&gt;              e.UserState;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;tuple = bigTuple.Item1;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;cevent = bigTuple.Item2;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;summaries = bigTuple.Item3;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;i = bigTuple.Item4;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;ticker = tuple.Item1;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;name = tuple.Item2;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;asset = tuple.Item3;
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;subAsset = tuple.Item4;

    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(e.Error == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;) {
        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;adjustedPrices =
                e.Result
                .Split(&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;[] { &lt;SPAN style="COLOR: #a31515"&gt;'\n' &lt;/SPAN&gt;})
                .Skip(&lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;)
                .Select(l =&amp;gt; l.Split(&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;[] { &lt;SPAN style="COLOR: #a31515"&gt;',' &lt;/SPAN&gt;}))
                .Where(l =&amp;gt; l.Length == &lt;SPAN style="COLOR: brown"&gt;7&lt;/SPAN&gt;)
                .Select(v =&amp;gt; &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Event&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Parse(v[&lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;]), &lt;SPAN style="COLOR: #2b91af"&gt;Double&lt;/SPAN&gt;.Parse(v[&lt;SPAN style="COLOR: brown"&gt;6&lt;/SPAN&gt;])));

        &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;timeSeries = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TimeSeries&lt;/SPAN&gt;(ticker, name, asset, subAsset, adjustedPrices);
        summaries[i] = timeSeries.GetSummary();
        cevent.Signal();
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.Write(&lt;SPAN style="COLOR: #a31515"&gt;"{0} "&lt;/SPAN&gt;, ticker);
    }
    &lt;SPAN style="COLOR: blue"&gt;else &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"[{0} ERROR] "&lt;/SPAN&gt;, ticker);
        &lt;SPAN style="COLOR: green"&gt;//Console.WriteLine(e.Error);
        &lt;/SPAN&gt;summaries[i] = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Summary&lt;/SPAN&gt;(ticker, name, &lt;SPAN style="COLOR: #a31515"&gt;"ERROR"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"ERROR"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;, &lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;, &lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;, &lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;, &lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;, &lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;,&lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;,&lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;); 
        cevent.Signal();
    }
}&lt;/PRE&gt;
&lt;P&gt;We first unpack the &lt;EM&gt;Tuple&lt;/EM&gt; we sent out originally, we then extract the Date and Price, create a &lt;EM&gt;Summary &lt;/EM&gt;object and store it in the &lt;EM&gt;summaries&lt;/EM&gt; array. It’s important to remember to &lt;EM&gt;Signal&lt;/EM&gt; to the &lt;EM&gt;cevent&lt;/EM&gt; in the error case as well because we want to print out the results even if some downloading failed.&lt;/P&gt;
&lt;P&gt;And here is what you get for your effort:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/BecomingreallyrichwithC_C128/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/BecomingreallyrichwithC_C128/image_2.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/BecomingreallyrichwithC_C128/image_thumb.png" width=743 height=506 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/BecomingreallyrichwithC_C128/image_thumb.png"&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9896982" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/lucabol/attachment/9896982.ashx" length="15441" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/lucabol/archive/tags/C_2300_+Programming/default.aspx">C# Programming</category></item><item><title>LAgent: an agent framework in F# – Part IX – Counting words …</title><link>http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx</link><pubDate>Sat, 19 Sep 2009 00:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9895168</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9895168.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9895168</wfw:commentRss><description>&lt;P&gt;Download framework &lt;A href="http://code.msdn.microsoft.com/LAgent" mce_href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;All posts are here:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Let’s now use our mapReduce to do something more interesting, for example finding the frequency of words in several books. Now the agent that processes the output needs to be a bit more complex.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;gathererF = &lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;msg (data:List&amp;lt;string * int&amp;gt;, counter, step) &lt;SPAN style="COLOR: blue"&gt;-&amp;gt;
                    match &lt;/SPAN&gt;msg &lt;SPAN style="COLOR: blue"&gt;with
                    &lt;/SPAN&gt;| Reduced(key, value)   &lt;SPAN style="COLOR: blue"&gt;-&amp;gt;
                        if &lt;/SPAN&gt;counter % step = &lt;SPAN style="COLOR: brown"&gt;0 &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;then
                            &lt;/SPAN&gt;printfn &lt;SPAN style="COLOR: maroon"&gt;"Processed %i words. Now processing %s" &lt;/SPAN&gt;counter key 
                        data.Add((key, value |&amp;gt; Seq.hd))
                        data, counter + &lt;SPAN style="COLOR: brown"&gt;1&lt;/SPAN&gt;, step
                    | MapReduceDone         &lt;SPAN style="COLOR: blue"&gt;-&amp;gt;
                        &lt;/SPAN&gt;data
                        |&amp;gt; Seq.distinctBy (&lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;(key, _) &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;key.ToLower())
                        |&amp;gt; Seq.filter (&lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;(key, _) &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;not(key = &lt;SPAN style="COLOR: maroon"&gt;"" &lt;/SPAN&gt;|| key = &lt;SPAN style="COLOR: maroon"&gt;"\"" &lt;/SPAN&gt;||&lt;BR&gt;                                                             (fst (Double.TryParse(key)))))
                        |&amp;gt; Seq.to_array
                        |&amp;gt; Array.sortBy snd
                        |&amp;gt; Array.rev
                        |&amp;gt; Seq.take &lt;SPAN style="COLOR: brown"&gt;20
                        &lt;/SPAN&gt;|&amp;gt; Seq.iter (&lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;(key, value) &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;printfn &lt;SPAN style="COLOR: maroon"&gt;"%A\t\t%A" &lt;/SPAN&gt;key value)
                        printfn &lt;SPAN style="COLOR: maroon"&gt;"All done!!"
                        &lt;/SPAN&gt;data, counter, step                           
                    
&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;gatherer = spawnAgent gathererF (&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;List&amp;lt;string * int&amp;gt;(), &lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;, &lt;SPAN style="COLOR: brown"&gt;1000&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;Every time a new word is reduced, a message is printed out and the result is added to a running list. When everything is done such a list is printed out by first manipulating it to reduce weirdness and limit the number of items. BTW: there are at least two bugs in this code, maybe more (late night quick-and-dirty-see-if-the-algo-works kind of coding).&lt;/P&gt;
&lt;P&gt;We want to maximize the number of processors to use, so let’s split the books in chunks so that they can be operated in parallel. The code below roughly does it (I say roughly because it doesn’t chunk the lines in the right order, but for this particular case it doesn’t matter).&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;gatherer = spawnAgent gathererF (&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;List&amp;lt;string * int&amp;gt;(), &lt;SPAN style="COLOR: brown"&gt;0&lt;/SPAN&gt;, &lt;SPAN style="COLOR: brown"&gt;1000&lt;/SPAN&gt;)

&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;splitBook howManyBlocks fileName =
    &lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;buffers = Array.init howManyBlocks (&lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;_ &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; new &lt;/SPAN&gt;StringBuilder())
    fileName
    |&amp;gt; File.ReadAllLines
    |&amp;gt; Array.iteri (&lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;i line &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;buffers.[i % (howManyBlocks)].Append(line) |&amp;gt; ignore)
    buffers

&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;blocks1 = &lt;SPAN style="COLOR: maroon"&gt;"C:\Users\lucabol\Desktop\Agents\Agents\kjv10.txt" &lt;/SPAN&gt;|&amp;gt; splitBook &lt;SPAN style="COLOR: brown"&gt;100
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;blocks2 = &lt;SPAN style="COLOR: maroon"&gt;"C:\Users\lucabol\Desktop\Agents\Agents\warandpeace.txt" &lt;/SPAN&gt;|&amp;gt; splitBook &lt;SPAN style="COLOR: brown"&gt;100
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;input =
    blocks1
    |&amp;gt; Array.append blocks2
    |&amp;gt; Array.mapi (&lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;i b &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;i.ToString(), b.ToString())&lt;/PRE&gt;
&lt;P&gt;And let’s execute!!&lt;/P&gt;&lt;PRE class=code&gt;mapReduce input map reduce gatherer &lt;SPAN style="COLOR: brown"&gt;20 20 &lt;/SPAN&gt;partitionF&lt;/PRE&gt;
&lt;P&gt;On my machine I get the following, which could be the right result.&lt;/P&gt;&lt;PRE class=code&gt;"a"        16147
"And"        13071
"I"        11349
"unto"        8125
"as"        6400
"her"        5865
"which"        5544
"from"        5378
"at"        5175
"on"        5155
"have"        5135
"me"        5068
"my"        4629
"this"        3782
"out"        3653
"ye"        3399
"when"        3312
"an"        2841
"upon"        2558
"so"        2489
All done!!&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9895168" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – Part VIII - Implementing MapReduce (user model)</title><link>http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx</link><pubDate>Fri, 04 Sep 2009 23:57:48 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9891606</guid><dc:creator>lucabol</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9891606.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9891606</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For this post I use a newer version of the framework that I just uploaded on CodeGallery. In the process of using LAgent I grew more and more unhappy with the weakly typed way of sending messages. The code that implements that feature is nasty: full of upcasts and downcasts. I was losing faith in it. Bugs were cropping up in all sorts of scenarios (i.e. using generic union types as messages).&lt;/p&gt;  &lt;p&gt;In the end I decided to re-architecture the framework so to make it strongly typed. In essence now each agent can just receive messages of a single type. The limitations that this design choice introduces (i.e. more limited hot swapping) are compensated by the catching of errors at compile time and the streamlining of the code. I left the old framework on the site in case you disagree with me.&lt;/p&gt;  &lt;p&gt;In any case, today’s post is about &lt;em&gt;MapReduce&lt;/em&gt;. It assumes that you know what it is (link to the original Google paper that served as inspiration is here: &lt;a title="Google Research Publication- MapReduce" href="http://labs.google.com/papers/mapreduce.html"&gt;Google Research Publication- MapReduce&lt;/a&gt;). What would it take to implement an in-memory &lt;em&gt;MapReduce&lt;/em&gt; using my agent framework?&lt;/p&gt;  &lt;p&gt;Let’s start with the user model.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;mapReduce   (inputs:seq&amp;lt;'in_key * 'in_value&amp;gt;)
                (map:'in_key &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'in_value &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_key * 'out_value&amp;gt;)
                (reduce:'out_key &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_value&amp;gt; &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'reducedValues&amp;gt;)
                outputAgent
                M R partitionF =                &lt;/pre&gt;

&lt;p&gt;&lt;em&gt;mapReduce&lt;/em&gt; takes seven parameters:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;u&gt;inputs&lt;/u&gt;: a sequence of input key/value pairs. &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;map&lt;/u&gt;: this function operates on each input key/value pair. It&amp;#160; returns a sequence of output key/value pairs. The type of the output sequence can be different from the type of the inputs. &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;reduce&lt;/u&gt;: this function operates on an output key and all the values associated with it. It returns a sequence of reduced values (i.e. the average of all the values for this key) &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;ouputAgent&lt;/u&gt;: this is the agent that gets notified every time a new output key has been reduced and at the end when all the operation ends. &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;M&lt;/u&gt;: how many mapper agents to instantiate &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;R&lt;/u&gt;: how many reducer agents to instantiate &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;partitionF&lt;/u&gt;: the partition function used to choose which of the reducers is associated with a key &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s look at how to use this function to find how often each word is used in a set of files. First a simple partition function can be defined as:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;partitionF = &lt;span style="color: blue"&gt;fun &lt;/span&gt;key M &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;abs(key.GetHashCode()) % M &lt;/pre&gt;

&lt;p&gt;Given a key and some buckets, it picks one of the buckets. Its type is: ‘a –&amp;gt; int –&amp;gt; int, so it’s fairly reusable.&lt;/p&gt;

&lt;p&gt;Let’s also create a basic agent that just prints out the reduced values:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;printer = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt;
                            match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
                            &lt;/span&gt;| Reduced(key, value)   &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%A %A&amp;quot; &lt;/span&gt;key value
                            | MapReduceDone         &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;All done!!&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;The agent gets notified whenever a new key is reduced or the algorithm ends. It is useful to be notified immediately instead of waiting for everything to be done. If I hadn’t written this code using agents I would have not realized that possibility. I would simply have framed the problem as a function that takes an input and returns an output. Agents force you to think explicitly about the parallelism in your app. That’s a good thing.&lt;/p&gt;

&lt;p&gt;The mapping function simply split the content of a file into words and adds a word/1 pair to the list. I know that there are much better ways to do this (i.e. regular expressions for the parsing and summing words counts inside the function), but I wanted to test the basic framework capabilities and doing it this way does it better.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;map = &lt;span style="color: blue"&gt;fun &lt;/span&gt;(fileName:string) (fileContent:string) &lt;span style="color: blue"&gt;-&amp;gt;
            let &lt;/span&gt;l = &lt;span style="color: blue"&gt;new &lt;/span&gt;List&amp;lt;string * int&amp;gt;()
            &lt;span style="color: blue"&gt;let &lt;/span&gt;wordDelims = [|&lt;span style="color: maroon"&gt;' '&lt;/span&gt;;&lt;span style="color: maroon"&gt;','&lt;/span&gt;;&lt;span style="color: maroon"&gt;';'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'.'&lt;/span&gt;;&lt;span style="color: maroon"&gt;':'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'?'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'!'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'('&lt;/span&gt;;&lt;span style="color: maroon"&gt;')'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\n'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\t'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\f'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\r'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\b'&lt;/span&gt;|]
            fileContent.Split(wordDelims) |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;word &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;l.Add((word, &lt;span style="color: brown"&gt;1&lt;/span&gt;)))
            l :&amp;gt; seq&amp;lt;string * int&amp;gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The reducer function simply sums the various word statistics sent by the mappers:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;reduce = &lt;span style="color: blue"&gt;fun &lt;/span&gt;key (values:seq&amp;lt;int&amp;gt;) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;[values |&amp;gt; Seq.sum] |&amp;gt; seq&amp;lt;int&amp;gt;&lt;/pre&gt;

&lt;p&gt;Now we can create some fake input to check that it works:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;testInput = [&lt;span style="color: maroon"&gt;&amp;quot;File1&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;I was going to the airport when I saw someone crossing&amp;quot;&lt;/span&gt;;&lt;br /&gt;                               &lt;span style="color: maroon"&gt;&amp;quot;File2&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;I was going home when I saw you coming toward me&amp;quot;&lt;/span&gt;]   &lt;/pre&gt;

&lt;p&gt;And execute the &lt;em&gt;mapReduce&lt;/em&gt;:&lt;/p&gt;

&lt;pre class="code"&gt;mapReduce testInput map reduce printer &lt;span style="color: brown"&gt;2 2 &lt;/span&gt;partitionF&lt;/pre&gt;

&lt;p&gt;On my machine I get the following. You might get a different order because of the async/parallel processing involved. If I wanted a stable order I would need to change the &lt;em&gt;printer&lt;/em&gt; agent to cache results on &lt;em&gt;Reduced&lt;/em&gt; and process them on &lt;em&gt;MapReduceDone&lt;/em&gt; (see next post).&lt;/p&gt;

&lt;p&gt;&amp;quot;I&amp;quot; [4]
  &lt;br /&gt;&amp;quot;crossing&amp;quot; [1]

  &lt;br /&gt;&amp;quot;going&amp;quot; [2]

  &lt;br /&gt;&amp;quot;home&amp;quot; [1]

  &lt;br /&gt;&amp;quot;me&amp;quot; [1]

  &lt;br /&gt;&amp;quot;the&amp;quot; [1]

  &lt;br /&gt;&amp;quot;toward&amp;quot; [1]

  &lt;br /&gt;&amp;quot;airport&amp;quot; [1]

  &lt;br /&gt;&amp;quot;coming&amp;quot; [1]

  &lt;br /&gt;&amp;quot;saw&amp;quot; [2]

  &lt;br /&gt;&amp;quot;someone&amp;quot; [1]

  &lt;br /&gt;&amp;quot;to&amp;quot; [1]

  &lt;br /&gt;&amp;quot;was&amp;quot; [2]

  &lt;br /&gt;&amp;quot;when&amp;quot; [2]

  &lt;br /&gt;&amp;quot;you&amp;quot; [1]&lt;/p&gt;

&lt;p&gt;In the next post we’ll process some real books …&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9891606" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – part VII – An auction application</title><link>http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx</link><pubDate>Sat, 11 Jul 2009 02:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9682539</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9682539.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9682539</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Here is an application that uses the framework we have been creating. It is an auction application and it is described in more detail &lt;a href="http://codebetter.com/blogs/matthew.podwysocki/archive/2009/05/20/f-actors-revisited.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Let’s go through it.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;AuctionMessage =
  | Offer &lt;span style="color: blue"&gt;of &lt;/span&gt;int * AsyncAgent &lt;span style="color: green"&gt;// Make a bid
  &lt;/span&gt;| Inquire &lt;span style="color: blue"&gt;of &lt;/span&gt;AsyncAgent     &lt;span style="color: green"&gt;// Check the status
&lt;/span&gt;&lt;span style="color: blue"&gt;and &lt;/span&gt;AuctionReply =
  | StartBidding
  | Status &lt;span style="color: blue"&gt;of &lt;/span&gt;int * DateTime &lt;span style="color: green"&gt;// Asked sum and expiration
  &lt;/span&gt;| BestOffer                &lt;span style="color: green"&gt;// Ours is the best offer
  &lt;/span&gt;| BeatenOffer &lt;span style="color: blue"&gt;of &lt;/span&gt;int       &lt;span style="color: green"&gt;// Yours is beaten by another offer
  &lt;/span&gt;| AuctionConcluded &lt;span style="color: blue"&gt;of      &lt;/span&gt;&lt;span style="color: green"&gt;// Auction concluded
      &lt;/span&gt;AsyncAgent * AsyncAgent
  | AuctionFailed            &lt;span style="color: green"&gt;// Failed without any bids
  &lt;/span&gt;| AuctionOver              &lt;span style="color: green"&gt;// Bidding is closed
  
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;timeToShutdown = 3000
&lt;span style="color: blue"&gt;let &lt;/span&gt;bidIncrement = 10 &lt;/pre&gt;

&lt;p&gt;This is the format of the messages that the clients can send and the action agent can reply to. F# is really good at this sort of thing. First, we need an auction agent:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;auctionAgent seller minBid closing =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;agent = spawnAgent (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg (isConcluded, maxBid, maxBidder) &lt;span style="color: blue"&gt;-&amp;gt;
                            match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
                            &lt;/span&gt;| Offer (_, client) &lt;span style="color: blue"&gt;when &lt;/span&gt;isConcluded &lt;span style="color: blue"&gt;-&amp;gt;
                                &lt;/span&gt;client &amp;lt;-- AuctionOver
                                (isConcluded, maxBid, maxBidder)
                            | Offer(bid, client) &lt;span style="color: blue"&gt;when &lt;/span&gt;not(isConcluded) &lt;span style="color: blue"&gt;-&amp;gt;
                                if &lt;/span&gt;bid &amp;gt;= maxBid + bidIncrement &lt;span style="color: blue"&gt;then
                                    if &lt;/span&gt;maxBid &amp;gt;= minBid &lt;span style="color: blue"&gt;then &lt;/span&gt;maxBidder &amp;lt;-- BeatenOffer bid                  
                                    client &amp;lt;-- BestOffer
                                    (isConcluded, bid, client)
                                &lt;span style="color: blue"&gt;else
                                    &lt;/span&gt;client &amp;lt;-- BeatenOffer maxBid
                                    (isConcluded, maxBid, maxBidder)
                            | Inquire client    &lt;span style="color: blue"&gt;-&amp;gt;
                                &lt;/span&gt;client &amp;lt;-- Status(maxBid, closing)
                                (isConcluded, maxBid, maxBidder))
                            (&lt;span style="color: blue"&gt;false&lt;/span&gt;, (minBid - bidIncrement), spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;()))                             &lt;/pre&gt;

&lt;p&gt;Notice that, if the action is concluded, the agent replies to offers by sending an &lt;em&gt;AuctionOver&lt;/em&gt; message. If the auction is still open, then, in case the bid is higher than the max, it sets a new max and notify the two parties involved; otherwise it notifies the bidder that the offer wasn’t successful. Also you can ask for the status of the auction.&lt;/p&gt;

&lt;p&gt;This is what the code above says. Maybe the code is simpler than words. Anyhow, we need to treat the case where no message is received for some amount of time.&lt;/p&gt;

&lt;pre class="code"&gt;agent &amp;lt;-- SetTimeoutHandler
            (closing - DateTime.Now).Milliseconds
            (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(isConcluded: bool, maxBid, maxBidder) &lt;span style="color: blue"&gt;-&amp;gt;
                if &lt;/span&gt;maxBid &amp;gt;= minBid &lt;span style="color: blue"&gt;then
                  let &lt;/span&gt;reply = AuctionConcluded(seller, maxBidder)
                  maxBidder &amp;lt;-- reply
                  seller &amp;lt;-- reply
                &lt;span style="color: blue"&gt;else &lt;/span&gt;seller &amp;lt;-- AuctionFailed
                agent &amp;lt;-- SetTimeoutHandler
                    timeToShutdown
                    (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(_:bool, _:int,_:AsyncAgent) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;StopProcessing)
                ContinueProcessing (&lt;span style="color: blue"&gt;true&lt;/span&gt;, maxBid, maxBidder))   
agent            &lt;/pre&gt;

&lt;p&gt;We start by waiting for the amount of time to the closing of the auction. If we get no messages, then two things might happen: we have an offer that is more than the minimum or we don’t. If we do, we tell everyone that it’s finished. Otherwise, we tell the seller that its item wasn’t successful.&amp;#160; In any case, we prepare the agent to shutdown by setting its next timeout to be &lt;em&gt;timeoutToShutdown&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It is interesting that we set the timeout handler inside the timeout handler. This is not a problem because of the nature of message processing (aka it processes one message at the time).&lt;/p&gt;

&lt;p&gt;We then need a bunch of of symbols …&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;module &lt;/span&gt;Auction =
  &lt;span style="color: blue"&gt;let &lt;/span&gt;random = &lt;span style="color: blue"&gt;new &lt;/span&gt;Random()
  
  &lt;span style="color: blue"&gt;let &lt;/span&gt;minBid = 100
  &lt;span style="color: blue"&gt;let &lt;/span&gt;closing = DateTime.Now.AddMilliseconds 10000.
  
  &lt;span style="color: blue"&gt;let &lt;/span&gt;seller = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(msg:AuctionReply) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;())
  &lt;span style="color: blue"&gt;let &lt;/span&gt;auction = auctionAgent seller minBid closing&lt;/pre&gt;

&lt;p&gt;Not a very smart seller we have here … Next up is our definition of a client.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;c = spawnAgent (
                &lt;span style="color: blue"&gt;fun &lt;/span&gt;msg (max, current) &lt;span style="color: blue"&gt;-&amp;gt;
                    let &lt;/span&gt;processBid (aMax, aCurrent) =
                        &lt;span style="color: blue"&gt;if &lt;/span&gt;aMax &amp;gt;= top &lt;span style="color: blue"&gt;then
                            &lt;/span&gt;log &lt;span style="color: maroon"&gt;&amp;quot;too high for me&amp;quot;
                            &lt;/span&gt;(aMax, aCurrent)
                        &lt;span style="color: blue"&gt;elif &lt;/span&gt;aCurrent &amp;lt; aMax &lt;span style="color: blue"&gt;then
                              let &lt;/span&gt;aCurrent = aMax + increment
                              Thread.Sleep (1 + random.Next 1000)
                              auction &amp;lt;-- Offer(aCurrent, c)
                              (aMax, aCurrent)
                        &lt;span style="color: blue"&gt;else &lt;/span&gt;(aMax, aCurrent)                       
                    &lt;span style="color: blue"&gt;match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
                    &lt;/span&gt;| StartBidding      &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;auction &amp;lt;-- Inquire c
                        (max, current)
                    | Status(maxBid,_)  &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &amp;lt;| sprintf &lt;span style="color: maroon"&gt;&amp;quot;status(%d)&amp;quot; &lt;/span&gt;maxBid
                        &lt;span style="color: blue"&gt;let &lt;/span&gt;s = processBid (maxBid, current)
                        c &amp;lt;-- SetTimeoutHandler timeToShutdown (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;StopProcessing) 
                        s
                    | BestOffer &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &amp;lt;| sprintf &lt;span style="color: maroon"&gt;&amp;quot;bestOffer(%d)&amp;quot; &lt;/span&gt;current
                        processBid(max, current)
                    | BeatenOffer maxBid &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &amp;lt;| sprintf &lt;span style="color: maroon"&gt;&amp;quot;beatenOffer(%d)&amp;quot; &lt;/span&gt;maxBid
                        processBid(maxBid, current)
                    | AuctionConcluded(seller, maxBidder) &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &lt;span style="color: maroon"&gt;&amp;quot;auctionConcluded&amp;quot;
                        &lt;/span&gt;c &amp;lt;-- Stop
                        (max, current)
                    | AuctionOver &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &lt;span style="color: maroon"&gt;&amp;quot;auctionOver&amp;quot;
                        &lt;/span&gt;c &amp;lt;-- Stop
                        (max, current))
                 (0,0)
c&lt;/pre&gt;

&lt;p&gt;Something that I like about agents is the fact that you need to understand just small snippets of code at the time. For example, you can read the processing for BestOffer and figure out if it makes sense.&amp;#160; I have an easy time personalizing them as in : “Ok, the guy just got a notification that there has been a better offer, what is he going to do next?”.&lt;/p&gt;

&lt;p&gt;The code should be self explanatory for the most part. In essence, if you can offer more, do it otherwise wait for the auction to end. I’m not even sure the processing is completely right. I confess I’m just trying to do the same as Matthews code from the link above.&lt;/p&gt;

&lt;p&gt;We can then start up the whole thing and enjoy the cool output.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;open &lt;/span&gt;Auction

(client 1 20 200) &amp;lt;-- StartBidding
(client 2 10 300) &amp;lt;-- StartBidding
(client 3 30 150) &amp;lt;-- StartBidding
Console.ReadLine() |&amp;gt; ignore  &lt;/pre&gt;

&lt;p&gt;Now for the nasty part. Implementing the framework.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9682539" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – Part VI – Hot swapping of code (and something silly)</title><link>http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx</link><pubDate>Sat, 04 Jul 2009 01:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649341</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649341.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649341</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Hot swapping of code&lt;/h4&gt;  &lt;p&gt;Let’s get back a couple of steps and consider what happens when you get an error. Sure, your agent will continue processing messages, but it might be doing the wrong thing. Your message handling code might be buggy.&lt;/p&gt;  &lt;p&gt;Ideally you’d want to patch things on the fly. You’d want to replace the message processing code for an agent without stopping it.&lt;/p&gt;  &lt;p&gt;Here is how you do it:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;counter2 = spawnAgent (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;From %i to %i&amp;quot; &lt;/span&gt;state (state + msg);&lt;br /&gt;                                                                              state + msg) 0
counter2 &amp;lt;-- 2
                                         
counter2 &amp;lt;-- SetAgentHandler(&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state –&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;From %i to %i via multiplication&amp;quot; &lt;/span&gt;state (state * msg); msg * state)
counter2 &amp;lt;-- 3&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Which generates:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;From 0 to 2 
      &lt;br /&gt;From 2 to 6 via multiplication&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After the agent receives a &lt;em&gt;SetAgentHandler&lt;/em&gt; message, it switch from a ‘+’ agent to a ‘*’ agent on the fly!! All the messages that come after that one gets multiplied to the state. Also, the state is preserved between changes in behavior.&lt;/p&gt;

&lt;p&gt;It might not be immediately apparent how to load a function at runtime, but it is really simple. Imagine that I get the data on the function to load from somewhere (i.e. a management console UI).&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;assemblyNameFromSomewhere, typeNameFromSomewhere, methodNameFromSomewhere = &lt;br /&gt;                                                &lt;span style="color: maroon"&gt;&amp;quot;mscorlib.dll&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;System.Console&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;WriteLine&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;I can then use it to dynamically load a message handler (in this case &lt;em&gt;Console.Writeline&lt;/em&gt;).&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;a = Assembly.Load(assemblyNameFromSomewhere)
&lt;span style="color: blue"&gt;let &lt;/span&gt;c = a.GetType(typeNameFromSomewhere)
&lt;span style="color: blue"&gt;let &lt;/span&gt;m = c.GetMethod(methodNameFromSomewhere, [|&lt;span style="color: maroon"&gt;&amp;quot;&amp;quot;&lt;/span&gt;.GetType()|])
&lt;span style="color: blue"&gt;let &lt;/span&gt;newF = &lt;span style="color: blue"&gt;fun &lt;/span&gt;(msg:string) (state:obj) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;m.Invoke(&lt;span style="color: blue"&gt;null&lt;/span&gt;, [| (msg:&amp;gt;obj) |])&lt;/pre&gt;

&lt;p&gt;And then it is as simple as posting a &lt;em&gt;SetAgentHandler&lt;/em&gt;.&lt;/p&gt;

&lt;pre class="code"&gt;counter2 &amp;lt;-- SetAgentHandler(newF)
counter2 &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;blah&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now our &lt;em&gt;counter2&lt;/em&gt; agent has become an echo agent on the fly, having loaded &lt;em&gt;Console.WriteLine&lt;/em&gt; dynamically. Note how the agent moved from being a ‘+’ agent taking integers to being a ‘*’ agent taking integers to being an ‘echo’ agent taking strings. And it didn’t stop processing messages for the whole time.&lt;/p&gt;

&lt;p&gt;Obviously, you can do the same thing with workers:&lt;/p&gt;

&lt;pre class="code"&gt;echo &amp;lt;-- SetWorkerHandler(&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;I'm an echo and I say: %s&amp;quot; &lt;/span&gt;msg)
echo &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;And parallelWorkers:&lt;/p&gt;

&lt;pre class="code"&gt;parallelEcho &amp;lt;-- SetWorkerHandler(&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;tprint (&lt;span style="color: maroon"&gt;&amp;quot;I'm new and &amp;quot; &lt;/span&gt;+ msg))
messages |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;parallelEcho &amp;lt;-- msg)&lt;/pre&gt;

&lt;h4&gt;A silly interlude&lt;/h4&gt;

&lt;p&gt;As a way to show some agents talking to each other, here is a simple program that simulates marital interactions (of the worst kind):&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;husband = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(To, msg) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Husband says: %s&amp;quot; &lt;/span&gt;msg; To &amp;lt;-- msg)
&lt;span style="color: blue"&gt;let rec &lt;/span&gt;wife = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Wife says: screw you and your '%s'&amp;quot; &lt;/span&gt;msg)
husband &amp;lt;-- (wife, &lt;span style="color: maroon"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;)
husband &amp;lt;-- (wife, &lt;span style="color: maroon"&gt;&amp;quot;But darling ...&amp;quot;&lt;/span&gt;)
husband &amp;lt;-- (wife, &lt;span style="color: maroon"&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;Which produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Husband says: Hello 
      &lt;br /&gt;Husband says: But darling ... 

      &lt;br /&gt;Wife says: screw you and your 'Hello' 

      &lt;br /&gt;Wife says: screw you and your 'But darling ...' 

      &lt;br /&gt;Husband says: ok 

      &lt;br /&gt;Wife says: screw you and your 'ok'&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And yes, you cannot expect messages to be in the right sequence … Next up is an auction application.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649341" width="1" height="1"&gt;</description></item><item><title>LAgent: an agent framework in F# – Part V – Timeout management</title><link>http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx</link><pubDate>Sat, 27 Jun 2009 00:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649246</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649246.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649246</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Timeout management&lt;/h4&gt;  &lt;p&gt;Timeouts are very important in message based systems. In essence, if you are not getting messages for a certain period of time, that usually means something. It might be that something crashed, that other agents think that you are not online, or any other number of things. Hence the need to set timeouts and react when they are triggered.&lt;/p&gt;  &lt;p&gt;You do that by writing the following:&lt;/p&gt;  &lt;pre class="code"&gt;counter1 &amp;lt;--SetTimeoutHandler 1000 &lt;br /&gt;            (&lt;span style="color: blue"&gt;fun &lt;/span&gt;state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;I'm still waiting for a message in state %A, come on ...&amp;quot; &lt;br /&gt;                                                            &lt;/span&gt;state; ContinueProcessing(state))              &lt;/pre&gt;

&lt;p&gt;Which generates the following message every second:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;I'm still waiting for a message in state 2, come on ... 
      &lt;br /&gt;I'm still waiting for a message in state 2, come on .…&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first parameter to &lt;em&gt;SetTimeoutHandler&lt;/em&gt; is how long to wait before triggering the handler. The second parameter is the handler that gets called whenever no message is received for that amount of time. Notice that the handler takes the current state of the agent and returns &lt;em&gt;ContinueProcessing(state)&lt;/em&gt;.&amp;#160; This tells the agent to continue processing messages and sets the current state to &lt;em&gt;state&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The following code:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- 2&lt;/pre&gt;

&lt;p&gt;Then generates:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;I'm still waiting for a message in state 4, come on ... 
      &lt;br /&gt;I'm still waiting for a message in state 4, come on ...&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;ContinueProcessing&lt;/em&gt; is just one of the three possible values of the (terribly named) &lt;em&gt;AfterError&lt;/em&gt;:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;AfterError =
| ContinueProcessing &lt;span style="color: blue"&gt;of &lt;/span&gt;obj
| StopProcessing
| RestartProcessing&lt;/pre&gt;

&lt;p&gt;Let’s see what RestartProcessing does.&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- SetTimeoutHandler 1000  (&lt;span style="color: blue"&gt;fun &lt;/span&gt;state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Restart from state %A&amp;quot; &lt;/span&gt;state&lt;br /&gt;                                                                        ; RestartProcessing)&lt;/pre&gt;

&lt;p&gt;Which, as expected, generates a nice stream of:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Restart from state 0 
      &lt;br /&gt;Restart from state 0&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To bring things back to normal (aka no timeout) you can just pass –1 as in:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- SetTimeoutHandler -1  (&lt;span style="color: blue"&gt;fun &lt;/span&gt;state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;ContinueProcessing(state))&lt;/pre&gt;

&lt;p&gt;Also, you can stop the agent when a timeout occurs by returning the aptly named &lt;em&gt;StopProcessing&lt;/em&gt;:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- SetTimeoutHandler 1000  (&lt;span style="color: blue"&gt;fun &lt;/span&gt;state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Restart from state %A&amp;quot; &lt;/span&gt;state; &lt;br /&gt;                                                                             StopProcessing)&lt;/pre&gt;
Another interesting thing you might want to do is hot swapping of code. More on that in the next part … 

&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649246" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – Part IV – Custom error management</title><link>http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx</link><pubDate>Sat, 20 Jun 2009 00:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649197</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649197.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649197</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Custom error management&lt;/h4&gt;  &lt;p&gt;In the last part we saw what happens by default in the framework when an error occurs. But that might not be what you want. You might want to have your sophisticated error detection and recovery distributed algorithm.&lt;/p&gt;  &lt;p&gt;To make such a thing possible each agent has a manager. The manager is an agent that gets called whenever an error occurs in the agent it is monitoring.&lt;/p&gt;  &lt;p&gt;In code:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;manager = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(agent, name:string, ex:Exception, msg:obj,&lt;br /&gt;                 state, initialState) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%s restarting ...&amp;quot; &lt;/span&gt;name; agent &amp;lt;-- Restart)
counter1 &amp;lt;-- SetManager(manager)&lt;/pre&gt;

&lt;p&gt;Whenever an error is generated the manager receives a tuple of:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;(agent, name, exception, message, currentState, inititialState)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This manager prints out something and then restarts the agent. Let’s trigger an error by posting the wrong message:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;afdaf&amp;quot;
&lt;/span&gt;counter1 &amp;lt;-- 2&lt;/pre&gt;

&lt;p&gt;The expectation is that the counter will restart from 0 whenever an error is triggered. This is what happens:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Bob restarting ... 
      &lt;br /&gt;From 0 to 2&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which is what we expected. Obviously this is not a very sophisticated error recovery algorithm. You might want to do something more meaningful. Hopefully you have enough information to build whatever you need.&lt;/p&gt;

&lt;p&gt;A particularly important class of unexpected event is timeouts. We’ll talk about them next. &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649197" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – Part III – Default error management</title><link>http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx</link><pubDate>Sat, 13 Jun 2009 00:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649127</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649127.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649127</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Default error management&lt;/h4&gt;  &lt;p&gt;What happens when an error occurs? Well, ideally you want to notify someone and continue processing messages. By default you want to print the error and as much information as you can about it.&lt;/p&gt;  &lt;p&gt;Let’s first see what happens if you pass the wrong message type:&lt;/p&gt;  &lt;pre class="code"&gt;counter1 &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;fst&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;/span&gt;Generates:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&amp;gt; The exception below occurred on agent Undefined at state 3 with message &amp;quot;fst&amp;quot;. The agent was started with state 0. 
      &lt;br /&gt;System.InvalidCastException: Specified cast is not valid. 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.UnboxGeneric[T](Object source) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.f@158.Invoke(Object a, Object b) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.loop@20-3.Invoke(Unit unitVar) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Control.AsyncBuilderImpl.callA@245.Invoke(AsyncParams`1 args)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You get information about the current state of the agent, the message that generated the error, the initial state of the agent and the exception that was generated. But, in a system with several agents, you’d like to know which one agent failed. Then you need to name your agent:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- SetName(&lt;span style="color: maroon"&gt;&amp;quot;Bob&amp;quot;&lt;/span&gt;)
counter1 &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;fadfad&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now you get (important part in blue):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&amp;gt; The exception below occurred on agent &lt;font color="#0000ff"&gt;Bob&lt;/font&gt; at state 3 with message &amp;quot;fadfad&amp;quot;. The agent was started with state 0. 

      &lt;br /&gt;System.InvalidCastException: Specified cast is not valid. 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.UnboxGeneric[T](Object source) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.f@158.Invoke(Object a, Object b) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.loop@20-3.Invoke(Unit unitVar) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Control.AsyncBuilderImpl.callA@245.Invoke(AsyncParams`1 args)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important thing is that the agent continues running. It lives to fight another day. Hence:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- 3&lt;/pre&gt;

&lt;p&gt;Produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;From 3 to 6&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which shows that the agent is running and that it has kept its current state. Also errors can occur inside the message handler with a similar result:&lt;/p&gt;

&lt;pre class="code"&gt;(spawnAgent (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;state / msg) 100) &amp;lt;-- 0&lt;/pre&gt;

&lt;p&gt;Produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&amp;gt; The exception below occurred on agent Undefined at state 100 with message 0. The agent was started with state 100. 
      &lt;br /&gt;System.DivideByZeroException: Attempted to divide by zero. 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0013.it@48-3.Invoke(Int32 msg, Int32 state) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.f@158.Invoke(Object a, Object b) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.loop@20-3.Invoke(Unit unitVar) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Control.AsyncBuilderImpl.callA@245.Invoke(AsyncParams`1 args)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But this might not be what you want. You might want to customize what happens when an error occurs. We’ll talk about that next.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649127" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent : an agent framework in F# – Part II – Agents and control messages</title><link>http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx</link><pubDate>Sat, 06 Jun 2009 00:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649041</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649041.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649041</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Agents&lt;/h4&gt;  &lt;p&gt;Agents are entities that process messages and keep state between one message and the next. As such they need to be initialized with a lambda that takes a message and a state and returns a new state. In F# pseudo code: msg –&amp;gt; state –&amp;gt; newState. For example the following:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;counter = spawnAgent (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;state + msg) 0&lt;/pre&gt;

&lt;p&gt;This is a counter that starts from 0 and gets incremented by the value of the received message. Let’s make it print something when it receives a message:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;counter1 = spawnAgent&lt;br /&gt;                (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;From %i to %i&amp;quot; &lt;/span&gt;state (state + msg); state + msg) 0
counter1 &amp;lt;-- 3 
counter1 &amp;lt;-- 4&lt;/pre&gt;

&lt;p&gt;Which produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;From 0 to 3 
      &lt;br /&gt;From 3 to 7&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is no &lt;em&gt;spawnParallelAgent&lt;/em&gt;, because I couldn’t figure out its usage patterns. Maybe I don’t have enough creativity. Obviously &lt;em&gt;msg&lt;/em&gt; and &lt;em&gt;state&lt;/em&gt; could be of whatever type (in real application they end up being tuples more often than not).&lt;/p&gt;

&lt;h4&gt;Control messages&lt;/h4&gt;

&lt;p&gt;You can do things to agents. I’m always adding to them but at this stage they are:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Command =
| Restart
| Stop
| SetManager &lt;span style="color: blue"&gt;of &lt;/span&gt;AsyncAgent
| SetName &lt;span style="color: blue"&gt;of &lt;/span&gt;string&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Plus some others. I’ll describe most of them later on, right now I want to talk about &lt;em&gt;Restart&lt;/em&gt; and &lt;em&gt;Stop&lt;/em&gt;. You use the former like this:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- Restart
counter1 &amp;lt;-- 3&lt;/pre&gt;

&lt;p&gt;Which produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;From 0 to 3&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This should be somehow surprising to you. You would have thought that you could just post integers to a counter. This is not the case. You can post whatever object. This is useful because it allows to have a common model for passing all sort of messages, it allows for the agent not to be parameterized by the type of the message (and of state) so that you can store them in data structures and allows advanced scenarios (i.e. hot swapping of code).&lt;/p&gt;

&lt;p&gt;This is a debatable decision. I tried to get the best of strongly typing and dynamic typing, while keeping simplicity of usage. The implementation of this is kind of a mess though. We’ll get there.&lt;/p&gt;

&lt;p&gt;BTW: you use Stop just by posting Stop, which stops the agent (forever).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649041" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent : an agent framework in F# – Part I – Workers and ParallelWorkers</title><link>http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx</link><pubDate>Fri, 29 May 2009 23:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9648937</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9648937.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9648937</wfw:commentRss><description>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;&lt;/ul&gt;  &lt;h4&gt;Introduction&lt;/h4&gt;  &lt;p&gt;I like to try out different programming paradigms. I started out as an object oriented programmer. In university, I used Prolog. I then learned functional programming. I also experimented with various shared memory parallel paradigms (i.e. async, tasks and such). I now want to learn more about message based parallel programming (&lt;a href="http://www.amazon.com/Programming-Erlang-Software-Concurrent-World/dp/193435600X" mce_href="http://www.amazon.com/Programming-Erlang-Software-Concurrent-World/dp/193435600X"&gt;Erlang&lt;/a&gt; style). I’m convinced that doing so makes me a better programmer. Plus, I enjoy it …&lt;/p&gt;  &lt;p&gt;My usual learning style is to build a framework that replicates a particular programming model and then write code using it. In essence, I build a very constrained environment. For example, when learning functional programming, I didn’t use any OO construct for a while even if my programming language supports them.&lt;/p&gt;  &lt;p&gt;In this case, I built myself a little agent framework based on F# &lt;em&gt;MailboxProcessors&lt;/em&gt;. I could have used &lt;em&gt;MailboxProcessors&lt;/em&gt; directly, but they are too flexible for my goal. Even to write a simple one of these guys, you need to use async and recursion in a specific pattern, which I always forget. Also, there are multiple ways to to do Post. I wanted things to be as simple as possible. I was willing to sacrifice flexibility for that.&lt;/p&gt;  &lt;p&gt;Notice that there are serious efforts in this space (as &lt;a href="http://blogs.msdn.com/maestroteam/" mce_href="http://blogs.msdn.com/maestroteam/"&gt;Axum&lt;/a&gt;). This is not one of them. It’s just a simple thing I enjoy working on between one meeting and the next.&lt;/p&gt;  &lt;h4&gt;Workers and ParallelWorkers&lt;/h4&gt;  &lt;p&gt;The two major primitives are spawning an agent and posting a message.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;echo = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%s&amp;quot; &lt;/span&gt;msg)
echo &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;Hello guys!&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;font color="#000000"&gt;There are two kinds of agents in my system. A &lt;em&gt;worker&lt;/em&gt; is an agent that doesn’t keep any state between consecutive messages. It is a stateless guy. Notice that the lambda that you pass to create the agent is strongly typed (aka &lt;em&gt;msg&lt;/em&gt; is of type &lt;em&gt;string&lt;/em&gt;). Also notice that I overloaded the &lt;em&gt;&amp;lt;—&lt;/em&gt; operator to mean &lt;em&gt;Post&lt;/em&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;font color="#000000"&gt;Given that a worker is stateless, you can create a whole bunch of them and, when a message is posted, route it to one of them transparently.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;parallelEcho = spawnParallelWorker(&lt;span style="color: blue"&gt;fun &lt;/span&gt;s &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%s&amp;quot; &lt;/span&gt;s) 10
parallelEcho &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;Hello guys!”&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;font color="#000000"&gt;For example, in the above code, 10 workers are created and, when a message is posted, it gets routed to one of them (using a super duper innovative dispatching algorithm I’ll describe in the implementation part). This &lt;em&gt;parallelWorker&lt;/em&gt; guy is not really needed, you could easily built it out of the other primitives, but it is kind of cute.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;font color="#000000"&gt;To show the difference between a worker and a &lt;em&gt;parallelWorker&lt;/em&gt;, consider this:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;tprint s = printfn &lt;span style="color: maroon"&gt;&amp;quot;%s running on thread %i&amp;quot; &lt;/span&gt;s Thread.CurrentThread.ManagedThreadId
&lt;span style="color: blue"&gt;let &lt;/span&gt;echo1 = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;s &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;tprint s)
&lt;span style="color: blue"&gt;let &lt;/span&gt;parallelEcho1 = spawnParallelWorker(&lt;span style="color: blue"&gt;fun &lt;/span&gt;s &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;tprint s) 10

&lt;span style="color: blue"&gt;let &lt;/span&gt;messages = [&lt;span style="color: maroon"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;b&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;c&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;e&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;f&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;g&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;h&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;i&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;l&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;m&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;n&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;o&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;p&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;q&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;r&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;s&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;t&amp;quot;&lt;/span&gt;]
messages |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;echo1 &amp;lt;-- msg)
messages |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;parallelEcho1 &amp;lt;-- msg)&lt;/pre&gt;

&lt;p mce_keep="true"&gt;&amp;#160;&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The result of the &lt;em&gt;echo1&lt;/em&gt; iteration is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;a running on thread 11 
      &lt;br /&gt;b running on thread 11 

      &lt;br /&gt;c running on thread 11 

      &lt;br /&gt;d running on thread 11 

      &lt;br /&gt;…&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the result of the &lt;em&gt;parallelEcho1&lt;/em&gt; iteration is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;a running on thread 13 
      &lt;br /&gt;c running on thread 14 

      &lt;br /&gt;b running on thread 12 

      &lt;br /&gt;o running on thread 14 

      &lt;br /&gt;m running on thread 13 

      &lt;br /&gt;…&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice how the latter executes on multiple threads (but not in order). Next time I’ll talk about agents, control messages and error management.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9648937" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>Luke talks about F# on Channel9</title><link>http://blogs.msdn.com/lucabol/archive/2009/05/27/luke-talks-about-f-on-channel9.aspx</link><pubDate>Wed, 27 May 2009 19:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9635464</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9635464.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9635464</wfw:commentRss><description>&lt;p&gt;Here you go: &lt;a title="http://channel9.msdn.com/posts/Charles/Luke-Hoban-Latest-version-of-F-Released-Whats-the-story-Whats-next/" href="http://channel9.msdn.com/posts/Charles/Luke-Hoban-Latest-version-of-F-Released-Whats-the-story-Whats-next/"&gt;http://channel9.msdn.com/posts/Charles/Luke-Hoban-Latest-version-of-F-Released-Whats-the-story-Whats-next/&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9635464" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>A version of the AsyncCache found its way into the Parallel Programming samples …</title><link>http://blogs.msdn.com/lucabol/archive/2009/05/21/a-version-of-the-asynccache-found-its-way-into-the-parallel-programming-samples.aspx</link><pubDate>Thu, 21 May 2009 20:28:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9634050</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9634050.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9634050</wfw:commentRss><description>&lt;p&gt;Go &lt;a href="http://code.msdn.microsoft.com/ParExtSamples"&gt;here&lt;/a&gt; to download them. It is in \ParallelExtensionsExtras\CoordinationDataStructures. It has a slightly different design in that it returns Tasks. I’m trying to get &lt;a href="http://blogs.msdn.com/pfxteam"&gt;Stephen&lt;/a&gt; to blog about it so that you can compare them.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9634050" 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/F_2300_/default.aspx">F#</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/VB/default.aspx">VB</category></item><item><title>I talk about C# and VB Co-Evolution on Channel9 (and some F# …)</title><link>http://blogs.msdn.com/lucabol/archive/2009/05/14/i-talk-about-c-and-vb-co-evolution-on-channel9-and-some-f.aspx</link><pubDate>Thu, 14 May 2009 20:26:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9616619</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9616619.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9616619</wfw:commentRss><description>&lt;p&gt;The title says it all. If you are interested, go &lt;a href="http://channel9.msdn.com/posts/Charles/Luca-Bolognese-C-and-VBNET-Co-Evolution-The-Twain-Shall-Meet/#Page=2"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616619" 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/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></channel></rss>