<?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/b/lucabol/</link><description>This blog will be frozen on 2/19/2010. New one started at http://lucabolognese.wordpress.com/</description><dc:language>en-US</dc:language><generator>Telligent Community 5.6.583.19849 (Build: 5.6.583.19849)</generator><item><title>Luca Bolognese leaves Microsoft</title><link>http://blogs.msdn.com/b/lucabol/archive/2010/02/19/luca-bolognese-leaves-microsoft.aspx</link><pubDate>Fri, 19 Feb 2010 16:58:02 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9966435</guid><dc:creator>lucabol</dc:creator><slash:comments>15</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9966435</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2010/02/19/luca-bolognese-leaves-microsoft.aspx#comments</comments><description>&lt;p&gt;This is my last post on this blog. My new blog is here: &lt;a title="http://lucabolognese.wordpress.com/" href="http://lucabolognese.wordpress.com/"&gt;http://lucabolognese.wordpress.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I accepted a role as Director for Credit Suisse in London. I’m excited by the opportunity to work in the financial industry, a long-standing desire of mine. I’m also excited to write more F# code and to be closer to Italy, where my extended family is.&lt;/p&gt;  &lt;p&gt;The past ten years in Microsoft have been a wild ride. I’m proud to have been part of ObjectSpaces, Generics, LINQ and F# (and much more …). I’ve been lucky to be able to post on this blog and present at conferences about such innovative technologies. It has all been a lot of fun. I’m sure the next ten years will be as good.&lt;/p&gt;  &lt;p&gt;I’ll see you guys on my new blog.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9966435" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/C_2300_+Programming/">C# Programming</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/Object+Orientation/">Object Orientation</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/Books/">Books</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/Sport/">Sport</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/Miscellanea/">Miscellanea</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/Financial/">Financial</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/-NET+Futures/">.NET Futures</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/Statistics/">Statistics</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/VB/">VB</category></item><item><title>LChart: displaying charts in F# – Part I</title><link>http://blogs.msdn.com/b/lucabol/archive/2010/02/17/lchart-displaying-charts-in-f-part-i.aspx</link><pubDate>Wed, 17 Feb 2010 19:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9965255</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9965255</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2010/02/17/lchart-displaying-charts-in-f-part-i.aspx#comments</comments><description>&lt;P&gt;I want to use F# as a exploratory data analysis language (like &lt;A href="http://www.r-project.org/" mce_href="http://www.r-project.org/"&gt;R&lt;/A&gt;). But I don’t know how to get the same nice graphic capabilities. So I decided to create them. Here is a library to draw charts in F#. It steals ideas from &lt;A href="http://www.amazon.com/Grammar-Graphics-Leland-Wilkinson/dp/0387987746" mce_href="http://www.amazon.com/Grammar-Graphics-Leland-Wilkinson/dp/0387987746"&gt;this book&lt;/A&gt; and &lt;A href="http://had.co.nz/ggplot2/book/" mce_href="http://had.co.nz/ggplot2/book/"&gt;this R package&lt;/A&gt;. It is nothing more than a wrapper on top of the &lt;A href="http://www.microsoft.com/downloads/details.aspx?familyid=130F7986-BF49-4FE5-9CA8-910AE6EA442C&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?familyid=130F7986-BF49-4FE5-9CA8-910AE6EA442C&amp;amp;displaylang=en"&gt;Microsoft Chart Controls&lt;/A&gt; to give it a more ‘exploratory’ one line calling syntax. It is also rough work in progress: I don’t wrap all the chart types and there are bugs in the ones I wrap. Also the architecture is all wrong (more on this in another post). But it’s a start and it kind of works. Attached the full code.&lt;/P&gt;
&lt;P&gt;I will continue this series in my new blog at wordpress: &lt;A title=http://lucabolognese.wordpress.com/ href="http://lucabolognese.wordpress.com/" mce_href="http://lucabolognese.wordpress.com/"&gt;http://lucabolognese.wordpress.com/&lt;/A&gt;. The reason I need a new blog will be explained in an upcoming post.&lt;/P&gt;
&lt;P&gt;Part II is now &lt;A href="http://lucabolognese.wordpress.com/2010/02/17/lchart-displaying-charts-in-f-part-ii/" mce_href="http://lucabolognese.wordpress.com/2010/02/17/lchart-displaying-charts-in-f-part-ii/"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Ok, let’s start. How do I draw a chart?&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;x = [1.;2.5;3.1;4.;4.8;6.0;7.5;8.;9.1;15.]
&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;y = [1.6;2.1;1.4;4.;2.3;1.9;2.4;1.4;5.;2.9]

lc.scatter(x, y) |&amp;gt; display&lt;/PRE&gt;
&lt;P&gt;X and Y are just some make up data. &lt;EM&gt;lc&lt;/EM&gt; is the name of a class (????) and &lt;EM&gt;scatter&lt;/EM&gt; is a static method on it. &lt;EM&gt;scatter&lt;/EM&gt; doesn’t display the chart, it just produces a an object that represents the chart. &lt;EM&gt;Display&lt;/EM&gt; displays the chart. The reason for using the bizarre lc static class is that I want it to be short so that it is easy to type in the fsi.exe. At the same time it needs to support optional parameters (which are not supported on top level functions in F#).&lt;/P&gt;
&lt;P&gt;You get a window with this chart on it. You can press CTRL+C to copy it (as I did to post it here).&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_2.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb.png" width=382 height=295 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;You might want to customize the chart a bit by passing some of these famous optional parameters:&lt;/P&gt;&lt;PRE class=code&gt;lc.scatter(x = x, y = y, markerSize = 10, markerStyle = MarkerStyle.Diamond,
    xname = &lt;SPAN style="COLOR: maroon"&gt;"Players"&lt;/SPAN&gt;, yname = &lt;SPAN style="COLOR: maroon"&gt;"Ratings"&lt;/SPAN&gt;, title = &lt;SPAN style="COLOR: maroon"&gt;"Players' Ratings"&lt;/SPAN&gt;)  |&amp;gt; display     &lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_4.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_4.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_1.png" width=382 height=295 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_1.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Or you might want to print different types of charts:&lt;/P&gt;&lt;PRE class=code&gt;lc.line(y = y, markerSize = 10, markerStyle = MarkerStyle.Diamond, xname = &lt;SPAN style="COLOR: maroon"&gt;"Players"&lt;/SPAN&gt;, yname = &lt;SPAN style="COLOR: maroon"&gt;"Ratings"&lt;/SPAN&gt;, title = &lt;SPAN style="COLOR: maroon"&gt;"Players' Ratings"&lt;/SPAN&gt;, isValueShownAsLabel = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;,
    color = Color.Red) |&amp;gt; display       &lt;/PRE&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_6.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_6.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_2.png" width=373 height=289 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_2.png"&gt;&lt;/A&gt; &lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;PRE class=code&gt;lc.spline(x = x, y = y, markerSize = 10, markerStyle = MarkerStyle.Diamond, xname = &lt;SPAN style="COLOR: maroon"&gt;"Players"&lt;/SPAN&gt;, yname = &lt;SPAN style="COLOR: maroon"&gt;"Ratings"&lt;/SPAN&gt;,
    title = &lt;SPAN style="COLOR: maroon"&gt;"Players' Ratings"&lt;/SPAN&gt;, isValueShownAsLabel = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;, color = Color.Red) |&amp;gt; display &lt;/PRE&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_8.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_8.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_3.png" width=371 height=287 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_3.png"&gt;&lt;/A&gt; &lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;PRE class=code&gt;lc.stepline(x = x, y = y, markerSize = 10, markerStyle = MarkerStyle.Diamond, xname = &lt;SPAN style="COLOR: maroon"&gt;"Players"&lt;/SPAN&gt;, yname = &lt;SPAN style="COLOR: maroon"&gt;"Ratings"&lt;/SPAN&gt;,
    title = &lt;SPAN style="COLOR: maroon"&gt;"Players' Ratings"&lt;/SPAN&gt;, isValueShownAsLabel = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;, color = Color.Red) |&amp;gt; display&lt;/PRE&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_10.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_10.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_4.png" width=372 height=288 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_4.png"&gt;&lt;/A&gt; &lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;PRE class=code&gt;lc.bar(y = y, xname = &lt;SPAN style="COLOR: maroon"&gt;"Players"&lt;/SPAN&gt;, yname = &lt;SPAN style="COLOR: maroon"&gt;"Ratings"&lt;/SPAN&gt;, title = &lt;SPAN style="COLOR: maroon"&gt;"Players' Ratings"&lt;/SPAN&gt;, isValueShownAsLabel = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;,
    drawingStyle = &lt;SPAN style="COLOR: maroon"&gt;"Emboss"&lt;/SPAN&gt;) |&amp;gt; display      &lt;/PRE&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_12.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_12.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_5.png" width=351 height=265 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_5.png"&gt;&lt;/A&gt; &lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE class=code&gt;lc.column(y = y, xname = &lt;SPAN style="COLOR: maroon"&gt;"Players"&lt;/SPAN&gt;, yname = &lt;SPAN style="COLOR: maroon"&gt;"Ratings"&lt;/SPAN&gt;, title = &lt;SPAN style="COLOR: maroon"&gt;"Players' Ratings"&lt;/SPAN&gt;,
    isValueShownAsLabel = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;, drawingStyle = &lt;SPAN style="COLOR: maroon"&gt;"Cylinder"&lt;/SPAN&gt;) |&amp;gt; display   &lt;/PRE&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_14.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_14.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_6.png" width=375 height=283 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_6.png"&gt;&lt;/A&gt; &lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;PRE class=code&gt;lc.boxplot(y = y, xname = &lt;SPAN style="COLOR: maroon"&gt;"Players"&lt;/SPAN&gt;, yname = &lt;SPAN style="COLOR: maroon"&gt;"Ratings"&lt;/SPAN&gt;, title = &lt;SPAN style="COLOR: maroon"&gt;"Players' Ratings"&lt;/SPAN&gt;, color = Color.Blue, whiskerPercentile = 5, percentile = 30,
    showAverage = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;, showMedian = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;, showUnusualValues = &lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;) |&amp;gt; display    &lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_16.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_16.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_7.png" width=408 height=317 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_7.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Ok, the last one is weird. You probably want more than one boxplot in a chart. I'll show you how to do that in the next post.&lt;/P&gt;
&lt;P&gt;The next post will be on how to have more than one series on the same chart and more than one chart in the same windows. Something like the below:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_18.png" mce_href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_18.png"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=image border=0 alt=image src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_8.png" width=445 height=342 mce_src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LChartdisplayingchartsinFPartI_9F73/image_thumb_8.png"&gt;&lt;/A&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9965255" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-96-52-55/ChartPlotter.fsx" length="12406" type="application/fsharp-script" /><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>Excel Financial Functions upgraded to Visual Studio 2010 RC</title><link>http://blogs.msdn.com/b/lucabol/archive/2010/02/16/excel-financial-functions-upgraded-to-visual-studio-2010-rc.aspx</link><pubDate>Tue, 16 Feb 2010 22:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9962311</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9962311</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2010/02/16/excel-financial-functions-upgraded-to-visual-studio-2010-rc.aspx#comments</comments><description>&lt;p&gt;Here is a link to the home page: &lt;a title="http://code.msdn.microsoft.com/FinancialFunctions/Wiki/View.aspx?title=Home" href="http://code.msdn.microsoft.com/FinancialFunctions/Wiki/View.aspx?title=Home"&gt;http://code.msdn.microsoft.com/FinancialFunctions/Wiki/View.aspx?title=Home&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9962311" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>New version of LAgent compatible with VS 2010 RC online</title><link>http://blogs.msdn.com/b/lucabol/archive/2010/02/15/new-version-of-lagent-compatible-with-vs-2010-rc-online.aspx</link><pubDate>Mon, 15 Feb 2010 17:36:54 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9963719</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9963719</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2010/02/15/new-version-of-lagent-compatible-with-vs-2010-rc-online.aspx#comments</comments><description>&lt;p&gt;My crazy agent framework now works with RC: &lt;a title="http://code.msdn.microsoft.com/LAgent" href="http://code.msdn.microsoft.com/LAgent"&gt;http://code.msdn.microsoft.com/LAgent&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9963719" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>A simpler F# MailboxProcessor</title><link>http://blogs.msdn.com/b/lucabol/archive/2010/02/12/a-simpler-f-mailboxprocessor.aspx</link><pubDate>Fri, 12 Feb 2010 23:29:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9962927</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9962927</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2010/02/12/a-simpler-f-mailboxprocessor.aspx#comments</comments><description>&lt;p&gt;I always forget the pattern to use to create a functioning &lt;em&gt;MailboxProcessor&lt;/em&gt; in F#. I mean, which piece has to be async and how to structure the recursive loop. When I find myself in that kind of a situation situation, my instincts scream at me: “Wrap it and make it work how your mind expects it to work”. So here is a simplification of the paradigm.&lt;/p&gt;  &lt;p&gt;Let’s see how some standard &lt;em&gt;MailboxProcessor&lt;/em&gt; code looks like:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;counter0 =
    MailboxProcessor.Start(&lt;span style="color: blue"&gt;fun &lt;/span&gt;inbox &lt;span style="color: blue"&gt;-&amp;gt;
        let rec &lt;/span&gt;loop n =
            async { 
                    &lt;span style="color: blue"&gt;let! &lt;/span&gt;msg = inbox.Receive()
                    &lt;span style="color: blue"&gt;return! &lt;/span&gt;loop(n+msg) }
        loop 0)&lt;/pre&gt;

&lt;p&gt;This keeps a running sum of the messages it receives. The only part that is really unique to this guy is “n + msg”. All the rest is infrastructure.&lt;/p&gt;

&lt;p&gt;You’d probably prefer to write code like the following:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;counter1 = MailboxProcessor.SpawnAgent( (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg n &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;msg + n), 0)&lt;/pre&gt;

&lt;p&gt;Yep, just one line of code. But, is it possible? Let’s look at one way of doing it:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;AfterError&amp;lt;'state&amp;gt; =
| ContinueProcessing &lt;span style="color: blue"&gt;of &lt;/span&gt;'state
| StopProcessing
| RestartProcessing
    
&lt;span style="color: blue"&gt;type &lt;/span&gt;MailboxProcessor&amp;lt;'a&amp;gt; &lt;span style="color: blue"&gt;with

    static member public &lt;/span&gt;SpawnAgent&amp;lt;'b&amp;gt;(messageHandler :'a&lt;span style="color: blue"&gt;-&amp;gt;&lt;/span&gt;'b&lt;span style="color: blue"&gt;-&amp;gt;&lt;/span&gt;'b,&lt;br /&gt;                                        initialState : 'b, ?timeout:'b &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;int,
                                        ?timeoutHandler:'b &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;AfterError&amp;lt;'b&amp;gt;,&lt;br /&gt;                                        ?errorHandler:&lt;br /&gt;                                            Exception &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'a option &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'b &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;AfterError&amp;lt;'b&amp;gt;)&lt;br /&gt;                                        : MailboxProcessor&amp;lt;'a&amp;gt; =
        &lt;span style="color: blue"&gt;let &lt;/span&gt;timeout = defaultArg timeout (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;-1)
        &lt;span style="color: blue"&gt;let &lt;/span&gt;timeoutHandler = defaultArg timeoutHandler (&lt;span style="color: blue"&gt;fun &lt;/span&gt;state –&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                                                                  &lt;/span&gt;ContinueProcessing(state))
        &lt;span style="color: blue"&gt;let &lt;/span&gt;errorHandler = defaultArg errorHandler (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ _ state –&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                                                                  &lt;/span&gt;ContinueProcessing(state))
        MailboxProcessor.Start(&lt;span style="color: blue"&gt;fun &lt;/span&gt;inbox &lt;span style="color: blue"&gt;-&amp;gt;
            let rec &lt;/span&gt;loop(state) = async {
                &lt;span style="color: blue"&gt;let! &lt;/span&gt;msg = inbox.TryReceive(timeout(state))
                &lt;span style="color: blue"&gt;try
                    match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
                    &lt;/span&gt;| None      &lt;span style="color: blue"&gt;-&amp;gt; match &lt;/span&gt;timeoutHandler state &lt;span style="color: blue"&gt;with
                                    &lt;/span&gt;| ContinueProcessing(newState)    &lt;span style="color: blue"&gt;-&amp;gt;&lt;br /&gt;                                                                   return! &lt;/span&gt;loop(newState)
                                    | StopProcessing        &lt;span style="color: blue"&gt;-&amp;gt; return &lt;/span&gt;()
                                    | RestartProcessing     &lt;span style="color: blue"&gt;-&amp;gt; return! &lt;/span&gt;loop(initialState)
                    | Some(m)   &lt;span style="color: blue"&gt;-&amp;gt; return! &lt;/span&gt;loop(messageHandler m state)
                &lt;span style="color: blue"&gt;with
                &lt;/span&gt;| ex &lt;span style="color: blue"&gt;-&amp;gt; match &lt;/span&gt;errorHandler ex msg state &lt;span style="color: blue"&gt;with
                        &lt;/span&gt;| ContinueProcessing(newState)    &lt;span style="color: blue"&gt;-&amp;gt; return! &lt;/span&gt;loop(newState)
                        | StopProcessing        &lt;span style="color: blue"&gt;-&amp;gt; return &lt;/span&gt;()
                        | RestartProcessing     &lt;span style="color: blue"&gt;-&amp;gt; return! &lt;/span&gt;loop(initialState)
                }
            loop(initialState))&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The funny formatting is because I have to fit it in the small horizontal space of this blog. In any case, this is just a simple (?) wrapper for the &lt;em&gt;MailboxProcessor&lt;/em&gt; pattern. The function takes two necessary parameters and two optional ones:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;messageHandler&lt;/strong&gt;: a function to execute when a message comes in, it takes the message and the current state as parameters and returns the new state.&lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;initialState&lt;/strong&gt;: the initial state for the &lt;em&gt;MailboxProcessor&lt;/em&gt;&lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;timeoutHandler&lt;/strong&gt;: a function that is executed whenever a timeout occurs. It takes as a parameter the current state and returns one of &lt;em&gt;ContinueProcessing(newState), StopProcessing or RestartProcessing&lt;/em&gt;&lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;errorHandler&lt;/strong&gt;: a function that gets call if an exception is generated inside the &lt;em&gt;messageHandler&lt;/em&gt; function. It takes the exception, the message, the current state and returns &lt;em&gt;ContinueProcessing(newState), StopProcessing or RestartProcessing&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An example of how to use &lt;em&gt;errorHandler&lt;/em&gt; to implement the CountingAgent in the Expert F# book follows:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;msg = Increment &lt;span style="color: blue"&gt;of &lt;/span&gt;int | Fetch &lt;span style="color: blue"&gt;of &lt;/span&gt;AsyncReplyChannel&amp;lt;int&amp;gt; | Stop

&lt;span style="color: blue"&gt;exception &lt;/span&gt;StopException

&lt;span style="color: blue"&gt;type &lt;/span&gt;CountingAgent() =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;counter = MailboxProcessor.SpawnAgent((&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg n &lt;span style="color: blue"&gt;-&amp;gt;
                    match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
                    &lt;/span&gt;| Increment m &lt;span style="color: blue"&gt;-&amp;gt;  &lt;/span&gt;n + m
                    | Stop &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;raise(StopException)
                    | Fetch replyChannel &lt;span style="color: blue"&gt;-&amp;gt;
                        do &lt;/span&gt;replyChannel.Reply(n)
                        n
                  ), 0, errorHandler = (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ _ _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;StopProcessing))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;a.Increment(n) = counter.Post(Increment(n))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;a.Stop() = counter.Post(Stop)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;a.Fetch() = counter.PostAndReply(&lt;span style="color: blue"&gt;fun &lt;/span&gt;replyChannel &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;Fetch(replyChannel))    
        
&lt;span style="color: blue"&gt;let &lt;/span&gt;counter2 = CountingAgent()
counter2.Increment(1)
counter2.Fetch()
counter2.Increment(2)
counter2.Fetch()
counter2.Stop()                             &lt;/pre&gt;

&lt;p&gt;Sometimes your agent doesn’t need a state, it is purely stateless. Something as simple as the following:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;echo = MailboxProcessor&amp;lt;_&amp;gt;.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)&lt;/pre&gt;

&lt;p&gt;You can easily make that happen by using this toned down version of an agent, called worker:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;static member public &lt;/span&gt;SpawnWorker(messageHandler,  ?timeout, ?timeoutHandler,?errorHandler) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;timeout = defaultArg timeout (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;-1)
    &lt;span style="color: blue"&gt;let &lt;/span&gt;timeoutHandler = defaultArg timeoutHandler (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;ContinueProcessing(()))
    &lt;span style="color: blue"&gt;let &lt;/span&gt;errorHandler = defaultArg errorHandler (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;ContinueProcessing(()))
    MailboxProcessor.SpawnAgent((&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;messageHandler msg; ()),&lt;br /&gt;                                 (), timeout, timeoutHandler,&lt;br /&gt;                                 (&lt;span style="color: blue"&gt;fun &lt;/span&gt;ex msg _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;errorHandler ex msg))&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Given that they are parallel, you might want to run a whole bunch of them at the same time. You might want something that looks like a worker, but that, under the cover, execute each &lt;em&gt;messageHandler&lt;/em&gt; in parallel. Something like:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;msg1 = Message1 | Message2 &lt;span style="color: blue"&gt;of &lt;/span&gt;int | Message3 &lt;span style="color: blue"&gt;of &lt;/span&gt;string
            
&lt;span style="color: blue"&gt;let &lt;/span&gt;a = MailboxProcessor.SpawnParallelWorker(&lt;span style="color: blue"&gt;function
                &lt;/span&gt;| Message1 &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Message1&amp;quot;&lt;/span&gt;;
                | Message2 n &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Message2 %i&amp;quot; &lt;/span&gt;n;
                | Message3 _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;failwith &lt;span style="color: maroon"&gt;&amp;quot;I failed&amp;quot;
                &lt;/span&gt;, 10
                , errorHandler = (&lt;span style="color: blue"&gt;fun &lt;/span&gt;ex _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%A&amp;quot; &lt;/span&gt;ex; ContinueProcessing()))


a.Post(Message1)
a.Post(Message2(100))
a.Post(Message3(&lt;span style="color: maroon"&gt;&amp;quot;abc&amp;quot;&lt;/span&gt;))
a.Post(Message2(100))&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;In this example, the different messages, are likely to cause things to print out of order. Notice the number 10 above which is how many workers you want to process your messages. This is implemented by round-robin messages to the various workers:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;static member public &lt;/span&gt;SpawnParallelWorker(messageHandler, howMany, ?timeout,&lt;br /&gt;                                                        ?timeoutHandler,?errorHandler) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;timeout = defaultArg timeout (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;-1)
    &lt;span style="color: blue"&gt;let &lt;/span&gt;timeoutHandler = defaultArg timeoutHandler (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;ContinueProcessing(()))
    &lt;span style="color: blue"&gt;let &lt;/span&gt;errorHandler = defaultArg errorHandler (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ _ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;ContinueProcessing(()))
    MailboxProcessor&amp;lt;'a&amp;gt;.SpawnAgent((&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg (workers:MailboxProcessor&amp;lt;'a&amp;gt; array, index) &lt;span style="color: blue"&gt;-&amp;gt;
                                        &lt;/span&gt;workers.[index].Post msg
                                        (workers, (index + 1) % howMany))  
                                    , (Array.init howMany&lt;br /&gt;                                      (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;MailboxProcessor&amp;lt;'a&amp;gt;.SpawnWorker(&lt;br /&gt;                                                 messageHandler, timeout, timeoutHandler,&lt;br /&gt;                                                 errorHandler)), 0))&lt;/pre&gt;

&lt;p&gt;One drawback with the current code is that it doesn’t supports cancellations. It should be possible to wrap that too, but I haven’t done it (yet). If you don’t want to cut and paste the code, it is inside the AgentSystem.fs file &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;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9962927" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>The F#unctional Londoners Meetup Group</title><link>http://blogs.msdn.com/b/lucabol/archive/2010/02/11/the-f-unctional-londoners-meetup-group.aspx</link><pubDate>Thu, 11 Feb 2010 17:24:05 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9962054</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9962054</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2010/02/11/the-f-unctional-londoners-meetup-group.aspx#comments</comments><description>&lt;p&gt;If you live in London and work with F#, you should join &lt;a title="http://www.meetup.com/FSharpLondon/" href="http://www.meetup.com/FSharpLondon/"&gt;http://www.meetup.com/FSharpLondon/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Also, if you don’t work with F#, but you’d like too, and you live in London you should join it. Also if you don’t live in London, but you’d like to and you’d like not to work on F# … Ok, you get the point.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9962054" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>LAgent: an agent framework in F# – Part X – ActiveObject</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/12/10/lagent-an-agent-framework-in-f-part-x-activeobject.aspx</link><pubDate>Thu, 10 Dec 2009 18:09:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9935251</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9935251</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/12/10/lagent-an-agent-framework-in-f-part-x-activeobject.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you stare long enough at agents, you start to realize that they are just ‘glorified locks’. They are a convenient programming model to protect a resource from concurrent access. The programming model is convenient because both the client and the server can write their code without worrying about concurrency problems, and yet the program runs in parallel. Protecting a resource sounds a lot like state encapsulation and the concept of state encapsulation is what object orientation is all about.&lt;/p&gt;  &lt;p&gt;So you start thinking if there is a way to enhance vanilla objects to make them agents. You want to reuse all the concepts that you are familiar with (i.e. inheritance, visibility rules, etc…) and you want your clients to call agents as if they were calling normal objects. Obviously, under the cover, the method calls won’t execute immediately, but they would be queued. Let’s look at an example.&lt;/p&gt;  &lt;p&gt;This is our simple counter agent:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;CounterMessage =
| Add &lt;span style="color: blue"&gt;of &lt;/span&gt;int
| Print

&lt;span style="color: blue"&gt;let &lt;/span&gt;counterF = &lt;span style="color: blue"&gt;fun &lt;/span&gt;msg count &lt;span style="color: blue"&gt;-&amp;gt;
    match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| Add(i)    &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;count + i
    | Print     &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;The value is %i&amp;quot; &lt;/span&gt;count; count
    
&lt;span style="color: blue"&gt;let &lt;/span&gt;c1 = spawnAgent counterF &lt;span style="color: brown"&gt;0
&lt;/span&gt;c1 &amp;lt;-- Add(&lt;span style="color: brown"&gt;3&lt;/span&gt;)
c1 &amp;lt;—Print&lt;/pre&gt;

&lt;p&gt;As nice as this looks, there are unfamiliar things in this model:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The communication is through messages. This requires packing and unpacking which, albeit easy in F#, is unfamiliar and feels like machinery that we’d like to get rid off. &lt;/li&gt;

  &lt;li&gt;The management of state is bizarre, it gets passed into the lambda and returned from it instead of being represented as fields and properties on the agent &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My best attempt at creating an object-like syntax follows:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Counter() =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;count = &lt;span style="color: brown"&gt;0
    &lt;/span&gt;&lt;span style="color: blue"&gt;member &lt;/span&gt;c.Add x = w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;count &amp;lt;- count + x
        )
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.Print () = w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;The value is %i&amp;quot; &lt;/span&gt;count
        )&lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;c = &lt;span style="color: blue"&gt;new &lt;/span&gt;Counter()
c.Add &lt;span style="color: brown"&gt;3
&lt;/span&gt;c.Print&lt;/pre&gt;

&lt;p&gt;With this syntax, you write your agents like you write your vanilla classes except:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You need a private field of type &lt;em&gt;WorkQueue&lt;/em&gt; &lt;/li&gt;

  &lt;li&gt;You need to write your methods as lambdas passed to the &lt;em&gt;WorkQueue.Queue&lt;/em&gt; function &lt;/li&gt;

  &lt;li&gt;Your methods cannot return values &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most worrisome of these constraints is 2. because you can easily forget about it. If you do forget, then everything compiles just fine, but it doesn’t do what you expect. That’s pure badness. I haven’t found a way to enforce it. This is a place where the language could help me. Other than that, the whole model works rather nicely.&lt;/p&gt;

&lt;p&gt;Regarding the third point, you can concoct a programming model that allows you to return values from your methods. Here it is:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;member &lt;/span&gt;c.CountTask = w.QueueWithTask(&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
    &lt;/span&gt;count
    )
&lt;span style="color: blue"&gt;member &lt;/span&gt;c.CountAsync = w.QueueWithAsync(&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
    &lt;/span&gt;count
    )&lt;/pre&gt;

&lt;pre class="code"&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;The count using Task is %i&amp;quot; &lt;/span&gt;(c.CountTask.Result)&lt;/pre&gt;

&lt;p&gt;The first method returns a &lt;em&gt;Task;&lt;/em&gt; the second method returns an &lt;em&gt;AsyncResultCell&lt;/em&gt;. Both are ways to represent a &lt;a href="http://en.wikipedia.org/wiki/Future_(programming)"&gt;promise&lt;/a&gt;. The latter allows a natural integration with the async block in F# as in the following code:&lt;/p&gt;

&lt;pre class="code"&gt;Async.RunSynchronously (
            async {
                &lt;span style="color: blue"&gt;let! &lt;/span&gt;count = c.CountAsync
                printfn &lt;span style="color: maroon"&gt;&amp;quot;The countusing Async is %i&amp;quot; &lt;/span&gt;count
            })&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;As for myself, I don’t like methods returning values. Every time I use them, I end up going back and thinking about my problem in a traditional way, aka as method calls that return results, instead of thinking about it in a more actor oriented fashion. I end up waiting for these promises to be materialized and, by doing so, I limit the amount of parallelism that I unleash. As a matter of fact, the whole business of hiding the message passing nature of the programming model is dubious. It makes for a nicer syntax, but you need to make an extra effort in your mind to translate it to what it really is: just message passing with a nice syntactical veneer. I haven’t decided yet which model I like the most.&lt;/p&gt;

&lt;p&gt;You should have a sense of what &lt;em&gt;WorkQueue&lt;/em&gt; is. In essence, it is a &lt;em&gt;Mailbox&lt;/em&gt; of lambdas (look at the red bold code below). &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;WorkQueue() =
    &lt;font color="#ff0000"&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;workQueue = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;f &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;f())&lt;/strong&gt;&lt;/font&gt;
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.Queue (f) = workQueue &amp;lt;-- f
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.QueueWithTask f : Task&amp;lt;'T&amp;gt; =
        &lt;span style="color: blue"&gt;let &lt;/span&gt;source = &lt;span style="color: blue"&gt;new &lt;/span&gt;TaskCompletionSource&amp;lt;_&amp;gt;()
        workQueue &amp;lt;-- (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;f() |&amp;gt; source.SetResult)
        source.Task
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.QueueWithAsync (f:unit &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'T) : Async&amp;lt;'T&amp;gt; =
        &lt;span style="color: blue"&gt;let &lt;/span&gt;result = &lt;span style="color: blue"&gt;new &lt;/span&gt;AsyncResultCell&amp;lt;'T&amp;gt;()
        workQueue &amp;lt;-- (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;f() |&amp;gt; result.RegisterResult )
        result.AsyncWaitResult
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.Restart () = workQueue &amp;lt;-! Restart
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.Stop () = workQueue &amp;lt;-! Stop
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.SetErrorHandler(h) =
        &lt;span style="color: blue"&gt;let &lt;/span&gt;managerF = &lt;span style="color: blue"&gt;fun &lt;/span&gt;(_, name:string, ex:Exception, _, _, _) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;h name ex                             
        &lt;span style="color: blue"&gt;let &lt;/span&gt;manager = spawnWorker managerF
        workQueue &amp;lt;-! SetManager manager
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.SetName(name) = workQueue &amp;lt;-! SetName(name)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.SetQueueHandler(g) = workQueue &amp;lt;-! SetWorkerHandler(g)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.SetTimeoutHandler(timeout, f) = workQueue &amp;lt;-! SetTimeoutHandler(timeout, f)&lt;/pre&gt;

&lt;p&gt;I implemented all the services that are in the message passing model. The two are equivalent as expressing power goes. In case you wonder how a real piece of code looks like using this model, here is an &lt;em&gt;ActiveObject&lt;/em&gt; version of the map reduce algorithm. One of these days, I will gather the strength to go trough this code and explain what it does, but not today :-)&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;#load &lt;/span&gt;&lt;span style="color: maroon"&gt;&amp;quot;AgentSystem.fs&amp;quot;
&lt;/span&gt;&lt;span style="color: blue"&gt;open &lt;/span&gt;AgentSystem.LAgent
&lt;span style="color: blue"&gt;open &lt;/span&gt;System
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Collections
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Collections.Generic
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Threading

&lt;span style="color: blue"&gt;type &lt;/span&gt;IOutput&amp;lt;'out_key, 'out_value&amp;gt; =
    &lt;span style="color: blue"&gt;abstract &lt;/span&gt;Reduced: '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;unit
    &lt;span style="color: blue"&gt;abstract &lt;/span&gt;MapReduceDone: unit &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;unit
    
&lt;span style="color: blue"&gt;type &lt;/span&gt;Mapper&amp;lt;'in_key, 'in_value, 'my_out_key, 'out_value &lt;span style="color: blue"&gt;when &lt;/span&gt;'my_out_key : comparison&amp;gt;&lt;br /&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;'my_out_key * 'out_value&amp;gt;, i, partitionF) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;reducerTracker: BitArray = &lt;span style="color: blue"&gt;null
    let mutable &lt;/span&gt;controller = Unchecked.defaultof&amp;lt;Controller&amp;lt;'in_key, 'in_value, 'my_out_key, 'out_value&amp;gt;&amp;gt;
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;reducers = Unchecked.defaultof&amp;lt;Reducer&amp;lt;'in_key, 'in_value, 'my_out_key, 'out_value&amp;gt; array&amp;gt;
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Init c reds =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;controller &amp;lt;- c
            reducers &amp;lt;- reds
            reducerTracker &amp;lt;- &lt;span style="color: blue"&gt;new &lt;/span&gt;BitArray(reducers.Length, &lt;span style="color: blue"&gt;false&lt;/span&gt;))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Process inKey inValue =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            let &lt;/span&gt;outKeyValues = map inKey inValue
            outKeyValues |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(outKey, outValue) &lt;span style="color: blue"&gt;-&amp;gt;
                                        let &lt;/span&gt;reducerUsed = partitionF outKey (reducers.Length)
                                        reducerTracker.Set(reducerUsed, &lt;span style="color: blue"&gt;true&lt;/span&gt;)
                                        reducers.[reducerUsed].Add(outKey, outValue)))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Done () =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;controller.MapDone i reducerTracker)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Stop () = w.Stop ()            
    
&lt;span style="color: blue"&gt;and &lt;/span&gt;Reducer&amp;lt;'in_key, 'in_value, 'out_key, 'out_value &lt;span style="color: blue"&gt;when &lt;/span&gt;'out_key :&lt;br /&gt;                     comparison&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;'out_value&amp;gt;, i, output:IOutput&amp;lt;'out_key, 'out_value&amp;gt;) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;workItems = &lt;span style="color: blue"&gt;new &lt;/span&gt;List&amp;lt;'out_key * 'out_value&amp;gt;()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;controller = Unchecked.defaultof&amp;lt;Controller&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt;&amp;gt;
    &lt;span style="color: blue"&gt;member &lt;/span&gt;r.Init c =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;controller &amp;lt;- c)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;r.StartReduction () =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;workItems
            |&amp;gt; Seq.groupBy fst
            |&amp;gt; Seq.sortBy fst
            |&amp;gt; Seq.map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(key, values) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;(key, reduce key (values |&amp;gt; Seq.map snd)))
            |&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;output.Reduced key value)
            controller.ReductionDone i) 
    &lt;span style="color: blue"&gt;member &lt;/span&gt;r.Add (outKey:'out_key, outValue:'out_value) : unit =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;workItems.Add((outKey, outValue)))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Stop () = w.Stop ()            
                
&lt;span style="color: blue"&gt;and &lt;/span&gt;Controller&amp;lt;'in_key, 'in_value, 'out_key, 'out_value &lt;span style="color: blue"&gt;when &lt;/span&gt;'out_key : comparison&amp;gt;(output:IOutput&amp;lt;'out_key, 'out_value&amp;gt;) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;mapperTracker: BitArray = &lt;span style="color: blue"&gt;null
    let mutable &lt;/span&gt;reducerUsedByMappers: BitArray = &lt;span style="color: blue"&gt;null
    let mutable &lt;/span&gt;reducerDone: BitArray = &lt;span style="color: blue"&gt;null
    let mutable &lt;/span&gt;mappers = Unchecked.defaultof&amp;lt;Mapper&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt; array&amp;gt;
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;reducers = Unchecked.defaultof&amp;lt;Reducer&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt; array&amp;gt;
    &lt;span style="color: blue"&gt;let &lt;/span&gt;BAtoSeq (b:BitArray) = [&lt;span style="color: blue"&gt;for &lt;/span&gt;x &lt;span style="color: blue"&gt;in &lt;/span&gt;b &lt;span style="color: blue"&gt;do yield &lt;/span&gt;x]
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.Init maps reds =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;mappers &amp;lt;- maps
            reducers &amp;lt;- reds
            mapperTracker &amp;lt;- &lt;span style="color: blue"&gt;new &lt;/span&gt;BitArray(mappers.Length, &lt;span style="color: blue"&gt;false&lt;/span&gt;)
            reducerUsedByMappers &amp;lt;- &lt;span style="color: blue"&gt;new &lt;/span&gt;BitArray(reducers.Length, &lt;span style="color: blue"&gt;false&lt;/span&gt;)
            reducerDone &amp;lt;- &lt;span style="color: blue"&gt;new &lt;/span&gt;BitArray(reducers.Length, &lt;span style="color: blue"&gt;false&lt;/span&gt;))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.MapDone (i : int) (reducerTracker : BitArray) : unit =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;mapperTracker.Set(i, &lt;span style="color: blue"&gt;true&lt;/span&gt;)
            &lt;span style="color: blue"&gt;let &lt;/span&gt;reducerUsedByMappers = reducerUsedByMappers.Or(reducerTracker)
            &lt;span style="color: blue"&gt;if &lt;/span&gt;not( BAtoSeq mapperTracker |&amp;gt; Seq.exists(&lt;span style="color: blue"&gt;fun &lt;/span&gt;bit &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;bit = &lt;span style="color: blue"&gt;false&lt;/span&gt;)) &lt;span style="color: blue"&gt;then
                &lt;/span&gt;BAtoSeq reducerUsedByMappers |&amp;gt; Seq.iteri (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i r &lt;span style="color: blue"&gt;-&amp;gt; if &lt;/span&gt;r = &lt;span style="color: blue"&gt;true then &lt;/span&gt;reducers.[i].StartReduction ())
                mappers |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;m &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;m.Stop ())
              )
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.ReductionDone (i: int) : unit =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;reducerDone.Set(i, &lt;span style="color: blue"&gt;true&lt;/span&gt;)
            &lt;span style="color: blue"&gt;if &lt;/span&gt;BAtoSeq reducerDone |&amp;gt; Seq.forall2 (&lt;span style="color: blue"&gt;fun &lt;/span&gt;x y &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;x = y) (BAtoSeq reducerUsedByMappers) &lt;span style="color: blue"&gt;then
                &lt;/span&gt;output.MapReduceDone ()
                reducers |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;r &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;r.Stop ())
                c.Stop()
             )         
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Stop () = w.Stop ()
                
&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;'out_value&amp;gt;)
                (output:IOutput&amp;lt;'out_key, 'out_value&amp;gt;)
                M R partitionF =
                    
    &lt;span style="color: blue"&gt;let &lt;/span&gt;len = inputs |&amp;gt; Seq.length
    &lt;span style="color: blue"&gt;let &lt;/span&gt;M = &lt;span style="color: blue"&gt;if &lt;/span&gt;len &amp;lt; M &lt;span style="color: blue"&gt;then &lt;/span&gt;len &lt;span style="color: blue"&gt;else &lt;/span&gt;M
    
    &lt;span style="color: blue"&gt;let &lt;/span&gt;mappers = Array.init M (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i &lt;span style="color: blue"&gt;-&amp;gt; new &lt;/span&gt;Mapper&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt;(map, i, partitionF))
    &lt;span style="color: blue"&gt;let &lt;/span&gt;reducers = Array.init R (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i &lt;span style="color: blue"&gt;-&amp;gt; new &lt;/span&gt;Reducer&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt;(reduce, i, output))
    &lt;span style="color: blue"&gt;let &lt;/span&gt;controller = &lt;span style="color: blue"&gt;new &lt;/span&gt;Controller&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt;(output)
    
    mappers |&amp;gt; Array.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;m &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;m.Init controller reducers)
    reducers |&amp;gt; Array.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;r &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;r. Init controller )
    controller.Init mappers reducers
    
    inputs |&amp;gt; Seq.iteri (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i (inKey, inValue) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;mappers.[i % M].Process inKey inValue)
    mappers |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;m &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;m.Done ())    

&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;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;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;span style="color: blue"&gt;let &lt;/span&gt;printer () =
  { &lt;span style="color: blue"&gt;new &lt;/span&gt;IOutput&amp;lt;string, int&amp;gt; &lt;span style="color: blue"&gt;with
        member &lt;/span&gt;o.Reduced key values = printfn &lt;span style="color: maroon"&gt;&amp;quot;%A %A&amp;quot; &lt;/span&gt;key values
        &lt;span style="color: blue"&gt;member &lt;/span&gt;o.MapReduceDone () = printfn &lt;span style="color: maroon"&gt;&amp;quot;All done!!&amp;quot;&lt;/span&gt;}
    
&lt;span style="color: blue"&gt;let &lt;/span&gt;testInput =&lt;br /&gt;     [&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;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;]   
mapReduce testInput map reduce (printer ()) &lt;span style="color: brown"&gt;2 2 &lt;/span&gt;partitionF

&lt;span style="color: blue"&gt;open &lt;/span&gt;System.IO
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Text

&lt;span style="color: blue"&gt;let &lt;/span&gt;gatherer(step) =
  &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
  &lt;span style="color: blue"&gt;let &lt;/span&gt;data = &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;counter = ref &lt;span style="color: brown"&gt;0 
  &lt;/span&gt;{ &lt;span style="color: blue"&gt;new &lt;/span&gt;IOutput&amp;lt;string, int&amp;gt; &lt;span style="color: blue"&gt;with
        member &lt;/span&gt;o.Reduced key values =
            w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &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;&amp;quot;Processed %i words. Now processing %s&amp;quot; &lt;/span&gt;!counter key 
                data.Add((key, values |&amp;gt; Seq.hd))
                counter := !counter + &lt;span style="color: brown"&gt;1&lt;/span&gt;)
        &lt;span style="color: blue"&gt;member &lt;/span&gt;o.MapReduceDone () =
            w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &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;&amp;quot;&amp;quot; &lt;/span&gt;|| key = &lt;span style="color: maroon"&gt;&amp;quot;\&amp;quot;&amp;quot; &lt;/span&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;&amp;quot;%A\t\t%A&amp;quot; &lt;/span&gt;key value)
                printfn &lt;span style="color: maroon"&gt;&amp;quot;All done!!&amp;quot;&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: blue"&gt;__SOURCE_DIRECTORY__ &lt;/span&gt;+ &lt;span style="color: maroon"&gt;&amp;quot;\kjv10.txt&amp;quot; &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: blue"&gt;__SOURCE_DIRECTORY__ &lt;/span&gt;+ &lt;span style="color: maroon"&gt;&amp;quot;\warandpeace.txt&amp;quot; &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;span style="color: green"&gt;//mapReduce input map reduce (gatherer(1000)) 20 20 partitionF

&lt;/span&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;BookSplitter () =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;blocks = &lt;span style="color: blue"&gt;new &lt;/span&gt;List&amp;lt;string * string&amp;gt;()
    &lt;span style="color: blue"&gt;member &lt;/span&gt;b.Split howManyBlocks fileName =
            &lt;span style="color: blue"&gt;let &lt;/span&gt;b =
                fileName
                |&amp;gt; splitBook howManyBlocks
                |&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())
            blocks.AddRange(b)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;b.Blocks () =
            blocks.ToArray() :&amp;gt; seq&amp;lt;string * string&amp;gt;

&lt;span style="color: blue"&gt;type &lt;/span&gt;WordCounter () =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let &lt;/span&gt;words = &lt;span style="color: blue"&gt;new &lt;/span&gt;Dictionary&amp;lt;string,int&amp;gt;()
    &lt;span style="color: blue"&gt;let &lt;/span&gt;worker(wordCounter:WordCounter, ev:EventWaitHandle) =
          &lt;span style="color: blue"&gt;let &lt;/span&gt;w1 = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
          { &lt;span style="color: blue"&gt;new &lt;/span&gt;IOutput&amp;lt;string, int&amp;gt; &lt;span style="color: blue"&gt;with
                member &lt;/span&gt;o.Reduced key values =
                    w1.Queue (&lt;span style="color: blue"&gt;fun&lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;wordCounter.AddWord key (values |&amp;gt; Seq.hd))
                &lt;span style="color: blue"&gt;member &lt;/span&gt;o.MapReduceDone () =
                    w1.Queue(&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;ev.Set() |&amp;gt; ignore)
           }
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.AddWord word count =
            &lt;span style="color: blue"&gt;let &lt;/span&gt;exist, value = words.TryGetValue(word)
            &lt;span style="color: blue"&gt;if &lt;/span&gt;exist &lt;span style="color: blue"&gt;then
                &lt;/span&gt;words.[word] &amp;lt;- value + count
            &lt;span style="color: blue"&gt;else
                &lt;/span&gt;words.Add(word, count)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.Add fileName =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            let &lt;/span&gt;s = &lt;span style="color: blue"&gt;new &lt;/span&gt;BookSplitter()
            fileName |&amp;gt; s.Split &lt;span style="color: brown"&gt;100
            &lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;ev = &lt;span style="color: blue"&gt;new &lt;/span&gt;EventWaitHandle(&lt;span style="color: blue"&gt;false&lt;/span&gt;, EventResetMode.AutoReset)
            &lt;span style="color: blue"&gt;let &lt;/span&gt;blocks = s.Blocks ()
            mapReduce blocks map reduce (worker(c, ev)) &lt;span style="color: brown"&gt;20 20 &lt;/span&gt;partitionF
            ev.WaitOne() |&amp;gt; ignore
            )  
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.Words =
        w.QueueWithAsync (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;words |&amp;gt; Seq.to_array |&amp;gt; Array.map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;kv &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;kv.Key, kv.Value)
        )    

&lt;span style="color: blue"&gt;let &lt;/span&gt;wc = &lt;span style="color: blue"&gt;new &lt;/span&gt;WordCounter()
wc.Add (&lt;span style="color: blue"&gt;__SOURCE_DIRECTORY__ &lt;/span&gt;+ &lt;span style="color: maroon"&gt;&amp;quot;\kjv10.txt&amp;quot;&lt;/span&gt;)
wc.Add (&lt;span style="color: blue"&gt;__SOURCE_DIRECTORY__ &lt;/span&gt;+ &lt;span style="color: maroon"&gt;&amp;quot;\warandpeace.txt&amp;quot;&lt;/span&gt;)

&lt;span style="color: blue"&gt;let &lt;/span&gt;wordsToPrint = async {
                    &lt;span style="color: blue"&gt;let! &lt;/span&gt;words = wc.Words
                    &lt;span style="color: blue"&gt;return &lt;/span&gt;words
                        |&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;&amp;quot;&amp;quot; &lt;/span&gt;|| key = &lt;span style="color: maroon"&gt;&amp;quot;\&amp;quot;&amp;quot; &lt;/span&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;&amp;quot;%A\t\t%A&amp;quot; &lt;/span&gt;key value)}


Async.RunSynchronously wordsToPrint
                        
Thread.Sleep(&lt;span style="color: brown"&gt;15000&lt;/span&gt;)
printfn &lt;span style="color: maroon"&gt;&amp;quot;Closed session&amp;quot;               
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9935251" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>My PDC session is online - “Future directions for C# and Visual Basic”</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/11/23/my-pdc-session-is-online-future-directions-for-c-and-visual-basic.aspx</link><pubDate>Mon, 23 Nov 2009 21:17:44 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9927546</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9927546</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/11/23/my-pdc-session-is-online-future-directions-for-c-and-visual-basic.aspx#comments</comments><description>&lt;p&gt;In case you are training to play the part of a first generation Italian immigrant in a Broadway show or if you want to understand why I never short msft stock: &lt;a title="http://microsoftpdc.com/Sessions/FT11" href="http://microsoftpdc.com/Sessions/FT11"&gt;http://microsoftpdc.com/Sessions/FT11&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9927546" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/C_2300_+Programming/">C# Programming</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/-NET+Futures/">.NET Futures</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/VB/">VB</category></item><item><title>Luca at PDC 2009 next week</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/11/13/luca-at-pdc-2009-next-week.aspx</link><pubDate>Fri, 13 Nov 2009 18:49:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9922139</guid><dc:creator>lucabol</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9922139</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/11/13/luca-at-pdc-2009-next-week.aspx#comments</comments><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/b/lucabol/archive/tags/C_2300_+Programming/">C# Programming</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/-NET+Futures/">.NET Futures</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/VB/">VB</category></item><item><title>Becoming really rich with C#</title><link>http://blogs.msdn.com/b/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><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9896982</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/09/22/becoming-really-rich-with-c.aspx#comments</comments><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/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-89-69-82/SystemCodeAndData.zip" length="15441" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/C_2300_+Programming/">C# Programming</category></item><item><title>LAgent: an agent framework in F# – Part IX – Counting words …</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx</link><pubDate>Fri, 18 Sep 2009 21:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9895168</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9895168</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;ul&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;&amp;quot;Processed %i words. Now processing %s&amp;quot; &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;&amp;quot;&amp;quot; &lt;/span&gt;|| key = &lt;span style="color: maroon"&gt;&amp;quot;\&amp;quot;&amp;quot; &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;&amp;quot;%A\t\t%A&amp;quot; &lt;/span&gt;key value)
                        printfn &lt;span style="color: maroon"&gt;&amp;quot;All done!!&amp;quot;
                        &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;&amp;quot;C:\Users\lucabol\Desktop\Agents\Agents\kjv10.txt&amp;quot; &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;&amp;quot;C:\Users\lucabol\Desktop\Agents\Agents\warandpeace.txt&amp;quot; &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;&amp;quot;a&amp;quot;        16147
&amp;quot;And&amp;quot;        13071
&amp;quot;I&amp;quot;        11349
&amp;quot;unto&amp;quot;        8125
&amp;quot;as&amp;quot;        6400
&amp;quot;her&amp;quot;        5865
&amp;quot;which&amp;quot;        5544
&amp;quot;from&amp;quot;        5378
&amp;quot;at&amp;quot;        5175
&amp;quot;on&amp;quot;        5155
&amp;quot;have&amp;quot;        5135
&amp;quot;me&amp;quot;        5068
&amp;quot;my&amp;quot;        4629
&amp;quot;this&amp;quot;        3782
&amp;quot;out&amp;quot;        3653
&amp;quot;ye&amp;quot;        3399
&amp;quot;when&amp;quot;        3312
&amp;quot;an&amp;quot;        2841
&amp;quot;upon&amp;quot;        2558
&amp;quot;so&amp;quot;        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></item><item><title>LAgent: an agent framework in F# – Part VIII - Implementing MapReduce (user model)</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx</link><pubDate>Fri, 04 Sep 2009 20:57:48 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9891606</guid><dc:creator>lucabol</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9891606</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;ul&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/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>LAgent: an agent framework in F# – part VII – An auction application</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx</link><pubDate>Fri, 10 Jul 2009 23:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9682539</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9682539</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;ul&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/b/lucabol/archive/tags/F_2300_/">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/b/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx</link><pubDate>Fri, 03 Jul 2009 22:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649341</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9649341</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt;&amp;#160; &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><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>LAgent: an agent framework in F# – Part V – Timeout management</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx</link><pubDate>Fri, 26 Jun 2009 21:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649246</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9649246</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&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/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>LAgent: an agent framework in F# – Part IV – Custom error management</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx</link><pubDate>Fri, 19 Jun 2009 21:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649197</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9649197</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt;&amp;#160; &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/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>LAgent: an agent framework in F# – Part III – Default error management</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx</link><pubDate>Fri, 12 Jun 2009 21:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649127</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9649127</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&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/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>LAgent : an agent framework in F# – Part II – Agents and control messages</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx</link><pubDate>Fri, 05 Jun 2009 21:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649041</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9649041</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&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/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>LAgent : an agent framework in F# – Part I – Workers and ParallelWorkers</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx</link><pubDate>Fri, 29 May 2009 20:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9648937</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9648937</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx#comments</comments><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;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;ul&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/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>Luke talks about F# on Channel9</title><link>http://blogs.msdn.com/b/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><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9635464</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/05/27/luke-talks-about-f-on-channel9.aspx#comments</comments><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/b/lucabol/archive/tags/F_2300_/">F#</category></item><item><title>A version of the AsyncCache found its way into the Parallel Programming samples …</title><link>http://blogs.msdn.com/b/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><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9634050</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/05/21/a-version-of-the-asynccache-found-its-way-into-the-parallel-programming-samples.aspx#comments</comments><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/b/lucabol/archive/tags/C_2300_+Programming/">C# Programming</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/VB/">VB</category></item><item><title>I talk about C# and VB Co-Evolution on Channel9 (and some F# …)</title><link>http://blogs.msdn.com/b/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><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9616619</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/05/14/i-talk-about-c-and-vb-co-evolution-on-channel9-and-some-f.aspx#comments</comments><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/b/lucabol/archive/tags/C_2300_+Programming/">C# Programming</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/VB/">VB</category></item><item><title>An Async Html cache – part II – Testing the cache</title><link>http://blogs.msdn.com/b/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><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9589057</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/05/08/an-async-html-cache-part-ii-testing-the-cache.aspx#comments</comments><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/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-58-90-57/AsyncCache_2E00_vb" length="4900" type="text/plain" /><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/-NET+Futures/">.NET Futures</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/VB/">VB</category></item><item><title>An Async Html cache – Part I - Writing the cache</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/04/27/an-async-html-cache-part-i.aspx</link><pubDate>Tue, 28 Apr 2009 02:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9572478</guid><dc:creator>lucabol</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9572478</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/04/27/an-async-html-cache-part-i.aspx#comments</comments><description>&lt;P&gt;Other posts:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#006bad&gt;&lt;A href="http://blogs.msdn.com/lucabol/" mce_href="http://blogs.msdn.com/lucabol/"&gt;Part II - Testing the cache&lt;/A&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;In the process of converting a financial VBA Excel Addin to .NET (more on that in later posts), I found myself in dire need of a HTML cache that can be called from multiple threads without blocking them. Visualize it as a glorified dictionary where each entry is (url, cachedHtml). The only difference is that when you get the page, you pass a callback to be invoked when the html has been loaded (which could be immediately if the html had already been retrieved by someone else).&lt;/P&gt;
&lt;P&gt;In essence, I want this:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Public Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;GetHtmlAsync(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;url &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;callback &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;))&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;I’m not a big expert in the &lt;A href="http://msdn.microsoft.com/en-us/concurrency/default.aspx" mce_href="http://msdn.microsoft.com/en-us/concurrency/default.aspx"&gt;.Net Parallel Extensions&lt;/A&gt;, but I’ve got &lt;A href="http://blogs.msdn.com/pfxteam" mce_href="http://blogs.msdn.com/pfxteam"&gt;help&lt;/A&gt;. Stephen Toub helped so much with this that he could have blogged about it himself. And, by the way, this code runs on Visual Studio 2010, which we haven’t shipped yet. I believe with some modifications, it can be run in 2008 + .Net Parallel Extensions CTP, but you’ll have to change a bunch of names.&lt;/P&gt;
&lt;P&gt;In any case, here it comes. First, let’s add some imports.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;Imports &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;System.Collections.Concurrent
&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Imports &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;System.Threading.Tasks
&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Imports &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;System.Threading
&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Imports &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;System.&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #0000a5"&gt;Net&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Then, let’s define an asynchronous cache.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;Public Class &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;AsyncCache&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;TKey, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #0000a5"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;)&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;This thing needs to store the (url, html) pairs somewhere and, luckily enough, there is an handy &lt;EM&gt;ConcurrentDictionary&lt;/EM&gt; that I can use. Also the cache needs to know how to load a &lt;EM&gt;TValue&lt;/EM&gt; given a &lt;EM&gt;TKey&lt;/EM&gt;. In ‘programmingese’, that means.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Private &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_loader &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Func&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TKey&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Private &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;ConcurrentDictionary&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TKey&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;))&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;I’ll need a way to create it.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Public Sub New&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;l &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Func&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TKey&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;))
        _loader = l
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Notice in the above code the use of the &lt;EM&gt;Task&lt;/EM&gt; class for my dictionary instead of &lt;EM&gt;TValue&lt;/EM&gt;. Task is a very good abstraction for “do some work asynchronously and call me when you are done”. It’s easy to initialize and it’s easy to attach callbacks to it. Indeed, this is what we’ll do next:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Public Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;GetValueAsync(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;key &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TKey&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;callback &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;))

        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Dim &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;task &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;) = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Nothing
        If Not &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryGetValue(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Then
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;task = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Function&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;() _loader(key), &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TaskCreationOptions&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.DetachedFromParent)
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;If &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryAdd(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Then
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Start()
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Else
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Cancel()
                _map.TryGetValue(key, task)
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End If
        End If

        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.ContinueWith(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Sub&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(t) callback(t.Result))
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End Sub&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Wow. Ok, let me explain. This method is divided in two parts. The first part is just a thread safe way to say “give me the task corresponding to this key or, if the task hasn’t been inserted in the cache yet, create it and insert it”. The second part just says “add callback to the list of functions to be called when the task has finished running”.&lt;/P&gt;
&lt;P&gt;The first part needs some more explanation. What is &lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TaskCreationOptions&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.DetachedFromParent? It essentially says that the created task is not going to prevent the parent task from terminating. In essence, the task that created the child task won’t wait for its conclusion. The rest is better explained in comments.&lt;/SPAN&gt;&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;If Not &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryGetValue(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Then &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' Is the task in the cache? (Loc. X)
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;task = &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Of &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TValue&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;)(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Function&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;() _loader(key), &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;TaskCreationOptions&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.DetachedFromParent) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' No, create it
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;If &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryAdd(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Then &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' Try to add it
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Start() &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' I succeeded. I’m the one who added this task. I can safely start it.
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;Else
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;task&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;.Cancel() &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' I failed, someone inserted the task after I checked in (Loc. X). Cancel it.
                &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;_map.TryGetValue(key, task) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;' And get the one that someone inserted
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: blue"&gt;End If
        End If&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Got it? Well, I admit I trust Stephen that this is what I should do …&lt;/P&gt;
&lt;P&gt;I can then create my little HTML Cache by using the above class as in:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="BACKGROUND: white"&gt;Public Class &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;HtmlCache
&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;
    Public Sub &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;GetHtmlAsync(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;url &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;callback &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;Action&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Of String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;))
        _asyncCache.GetValueAsync(url, callback)
    &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;End Sub

    Private Function &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;LoadWebPage(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;ByVal &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;url &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;) &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As String
        Using &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;client &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;WebClient&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;()
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: green"&gt;'Test.PrintThread("Downloading on thread {0} ...")
            &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Return &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;client.DownloadString(url)
        &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;End Using
    End Function

    Private &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;_asyncCache &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;As New &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: #2b91af"&gt;AsyncCache&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;Of String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;, &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;String&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;)(&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;AddressOf &lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white; COLOR: black"&gt;LoadWebPage)

&lt;/SPAN&gt;&lt;SPAN style="BACKGROUND: white"&gt;End Class&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;I have no idea why coloring got disabled when I copy/paste. It doesn’t matter, this is trivial. I just create an &lt;EM&gt;AsyncCache&lt;/EM&gt; and initialize it with a method that knows how to load a web page. I then simply implement &lt;EM&gt;GetHtmlAsync&lt;/EM&gt; by delegating to the underlying &lt;EM&gt;GetValueAsync&lt;/EM&gt; on &lt;EM&gt;AsyncCache&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;It is somehow bizarre to call &lt;EM&gt;Webclient.DownloadString&lt;/EM&gt;, when the design could be revised to take advantage of its asynchronous version. Maybe I’ll do it in another post. Next time, I’ll write code to use this thing.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9572478" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/-NET+Futures/">.NET Futures</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/VB/">VB</category></item><item><title>Luca at NDC in Oslo 17 – 19 June 2009</title><link>http://blogs.msdn.com/b/lucabol/archive/2009/03/24/luca-at-ndc-in-oslo-17-19-june-2009.aspx</link><pubDate>Tue, 24 Mar 2009 19:46:27 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9504664</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/lucabol/rsscomments.aspx?WeblogPostID=9504664</wfw:commentRss><comments>http://blogs.msdn.com/b/lucabol/archive/2009/03/24/luca-at-ndc-in-oslo-17-19-june-2009.aspx#comments</comments><description>&lt;p&gt;I’ll be speaking about the future of C# and F#. Oslo brings back so many memories …&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LucaatNDCinOslo1719June2009_8952/Logo%20NDC%202009_2.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Logo NDC 2009" border="0" alt="Logo NDC 2009" src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LucaatNDCinOslo1719June2009_8952/Logo%20NDC%202009_thumb.jpg" width="244" height="72" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;“one of the world’s most important conferences for IT developers and leaders”&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9504664" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/C_2300_+Programming/">C# Programming</category><category domain="http://blogs.msdn.com/b/lucabol/archive/tags/F_2300_/">F#</category></item></channel></rss>
