<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.microsoft.co.il/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>Bnaya Eshet : IDataflowBlock</title><link>http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IDataflowBlock/default.aspx</link><description>Tags: IDataflowBlock</description><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>Tpl Dataflow walkthrough - Part 5</title><link>http://blogs.microsoft.co.il/blogs/bnaya/archive/2012/01/28/tpl-dataflow-walkthrough-part-5.aspx</link><pubDate>Sat, 28 Jan 2012 17:04:31 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:1000032</guid><dc:creator>bnaya</dc:creator><slash:comments>0</slash:comments><description>&lt;h2&gt;Tpl Dataflow walkthrough - Part 5&lt;/h2&gt;  &lt;p&gt;this post is a &lt;strong&gt;complete walkthrough&lt;/strong&gt; of a &lt;strong&gt;web crawler&lt;/strong&gt; sample that was build purely by using &lt;strong&gt;Tpl Dataflow&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;it was built on &lt;strong&gt;.NET 4.5 / C# 5&lt;/strong&gt; (on a virtual machine using &lt;strong&gt;VS 11&lt;/strong&gt;).&lt;/p&gt;  &lt;p&gt;I will analyze each part of this sample, both by discussing the &lt;strong&gt;Dataflow&lt;/strong&gt; blocks and the &lt;strong&gt;patterns&lt;/strong&gt; in used.&lt;/p&gt;  &lt;p&gt;the sample code is available in &lt;a href="https://skydrive.live.com/redir.aspx?cid=9bf7c1a515d76a9a&amp;amp;resid=9BF7C1A515D76A9A!1404&amp;amp;parid=9BF7C1A515D76A9A!1321&amp;amp;authkey=!ACW2DtTH6k5CuTk" target="_blank"&gt;here&lt;/a&gt; (it is a VS 11 project).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/IMG_6257_60FC8823.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform" border="0" alt="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform" src="http://blogs.microsoft.co.il/blogs/bnaya/IMG_6257_thumb_5309F68E.png" width="405" height="307" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;during the walkthrough you will see the following &lt;strong&gt;Tpl Dataflow &lt;/strong&gt;blocks:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;TransformBlock &lt;/li&gt;    &lt;li&gt;TransformManyBlock &lt;/li&gt;    &lt;li&gt;ActionBlock &lt;/li&gt;    &lt;li&gt;BroadcastBlock &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;you will see how the &lt;strong&gt;aysnc / await&lt;/strong&gt; &lt;strong&gt;signature&lt;/strong&gt; of the &lt;strong&gt;Dataflow&lt;/strong&gt; &lt;strong&gt;blocks&lt;/strong&gt; is better for executing an&lt;strong&gt; IO bound operation&lt;/strong&gt; (without freezing a worker ThreadPool thread).&lt;/p&gt;  &lt;p&gt;I should also mention that this post is part of the &lt;strong&gt;Tpl Dataflow &lt;/strong&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TDF/default.aspx" target="_blank"&gt;series&lt;/a&gt; which you better read before reading this one.&lt;/p&gt;  &lt;p&gt;&lt;font color="#666666"&gt;Disclamation: the web crawler sample is for educational purpose only (running web crawler application may be forbidden by the low of your country).&lt;/font&gt;&lt;/p&gt;  &lt;h5&gt;The sample topography:&lt;/h5&gt;  &lt;p&gt;&lt;strong&gt;Tpl Dataflow&lt;/strong&gt; application is usually a collection of &lt;strong&gt;agents&lt;/strong&gt; which is linked together in order to compose a complete solution. &lt;strong&gt;each agent is having its own responsibilities and concerns&lt;/strong&gt;. the following diagram present the agent topography for this sample:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/image_7521B67A.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform" border="0" alt="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform" src="http://blogs.microsoft.co.il/blogs/bnaya/image_thumb_27E19722.png" width="520" height="405" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;h5&gt;agents block type and responsibilities&lt;/h5&gt;  &lt;p&gt;&lt;strong&gt;Downloader&lt;/strong&gt;: the responsibility of the downloader is to download the html of a web page. it is using a &lt;strong&gt;TransformBlock&amp;lt;Tin, Tout&amp;gt; &lt;/strong&gt;which belong to the executer block family. the transform block is getting a url as the input message and it produce the page&amp;#39;s html as it output.&lt;/p&gt;  &lt;p&gt;the transform block is construct from:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;input buffer (for url) &lt;/li&gt;    &lt;li&gt;task (do the transformation) &lt;/li&gt;    &lt;li&gt;output buffer (for the downloaded html) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;the &lt;strong&gt;task&lt;/strong&gt; is taking one message at a time from the input buffer, transform the message by a&lt;strong&gt; Func&amp;lt;Tin, Tout&amp;gt;&lt;/strong&gt; delegate which it get as a constructor parameter and put the result in the output buffer, where it is available for other blocks to consume.&lt;/p&gt;  &lt;p&gt;later we will see that our crawler transformation is actually taking &lt;strong&gt;Func&amp;lt;Tin, Task&amp;lt;Tout&amp;gt;&amp;gt; &lt;/strong&gt;which is a better signature for &lt;strong&gt;IO bound&lt;/strong&gt; operations (I will discuss it latter).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/image_5B79DDB3.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform" border="0" alt="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform" src="http://blogs.microsoft.co.il/blogs/bnaya/image_thumb_51D16F7D.png" width="400" height="120" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;the transform block is a propagator block which mean that it exposed both as a target and a source block. it is implementing &lt;strong&gt;IPropagatorBlock&amp;lt;Tin, Tout&amp;gt;&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;the following snippet show that &lt;strong&gt;IPropagatorBlock&lt;/strong&gt; is simply an encapsulation of &lt;strong&gt;ITargetBlock&lt;/strong&gt; and &lt;strong&gt;ISourceBlock&lt;/strong&gt;.&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:422eacdf-bea3-4f32-8922-a99ef267161e" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#fff;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IPropagatorBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; TInput, &lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; TOutput&amp;gt;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    : ITargetBlock&amp;lt;TInput&amp;gt;, &lt;/li&gt; &lt;li&gt;      ISourceBlock&amp;lt;TOutput&amp;gt;, &lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;      IDataflowBlock&lt;/li&gt; &lt;li&gt;{&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;h5&gt;Start crawling&lt;/h5&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:b05be473-d938-4ab3-995b-326a15e7dd7d" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#ddd;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2em;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; downloader = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;TransformBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt;(&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#0000ff;"&gt;async&lt;/span&gt; (url) =&amp;gt;&lt;/li&gt; &lt;li&gt;    {&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#008000;"&gt;// using IOCP the thread pool worker thread does return to the pool&lt;/span&gt;&lt;/li&gt; &lt;li&gt;        &lt;span style="color:#2b91af;"&gt;WebClient&lt;/span&gt; wc = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;WebClient&lt;/span&gt;();&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; result = &lt;span style="color:#0000ff;"&gt;await&lt;/span&gt; wc.DownloadStringTaskAsync(url);&lt;/li&gt; &lt;li&gt;        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; result;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    }, downloaderOptions);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;as I was mentioning earlier the downloader contractor is getting &lt;strong&gt;Func&amp;lt;Tin, Task&amp;lt;Tout&amp;gt;&amp;gt;&lt;/strong&gt;, therefore we can apply an async lambda expression (line 2). the code &lt;strong&gt;await&lt;/strong&gt; for downloading (at line 6). &lt;/p&gt;  &lt;p&gt;if you are not familiar with the &lt;strong&gt;async / await&lt;/strong&gt; concept you can read &lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/29/the-concept-of-async-await.aspx" target="_blank"&gt;this&lt;/a&gt; post or more posts in &lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/await/default.aspx" target="_blank"&gt;here&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;anyway &lt;strong&gt;while&lt;/strong&gt; &lt;strong&gt;awaiting&lt;/strong&gt; for the download (DownloadStringTaskAsync) the &lt;strong&gt;block&amp;#39;s task&lt;/strong&gt; is actually &lt;strong&gt;return its worker thread&lt;/strong&gt; to the ThreadPool and take advantage of the &lt;a href="http://en.wikipedia.org/wiki/Input/output_completion_port" target="_blank"&gt;IOCP&lt;/a&gt; (IO Completion Port), &lt;font color="#666666"&gt;this is an IO bound operation which mean that no CPU resources is needed &lt;/font&gt;&lt;font color="#666666"&gt;while the network card fetching the data from the network&lt;/font&gt;.     &lt;br /&gt;it is important to understand that while the network card is handling the request the &lt;strong&gt;agent&amp;#39;s task does not fetching another message from the buffer&lt;/strong&gt;, the task will be interrupt when the data will be available. &lt;/p&gt;  &lt;h5&gt;analyzing the html &lt;/h5&gt;  &lt;p&gt;the crawler is using 2 agent for analyze the downloaded html:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;link parser&lt;/strong&gt; (which will look for links elements &amp;lt;a href=&amp;quot;...&amp;quot;/&amp;gt;) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;image parser&lt;/strong&gt; (which will look for image elements &amp;lt;image src=&amp;quot;...&amp;quot;/&amp;gt;) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;both agent should be link to the downloader agent.    &lt;br /&gt;the problem is that &lt;strong&gt;linking both agent directly&lt;/strong&gt; to the downloader agent &lt;strong&gt;will result with starvation&lt;/strong&gt; of one of the agent.     &lt;br /&gt;unlike &lt;strong&gt;Rx&lt;/strong&gt; the most blocks forward messages into the first linked target that accept the message, and ignore other linked targets. which mean that the message will be handle by a single agent at a time.&lt;/p&gt;  &lt;p&gt;broadcast behavior can be achieved by using a &lt;strong&gt;BroadcastBlock&amp;lt;T&amp;gt;&lt;/strong&gt; which is part of the pure buffer family.     &lt;br /&gt;the broadcast block is construct from:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;input buffer &lt;/li&gt;    &lt;li&gt;task &lt;/li&gt;    &lt;li&gt;output buffer of single item. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/image_6A8096C0.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform, IPropagatorBlock" border="0" alt="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform, IPropagatorBlock" src="http://blogs.microsoft.co.il/blogs/bnaya/image_thumb_4BE6A617.png" width="421" height="125" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;the task is fetching a message from the input buffer and place it in the output buffer, from the output buffer the message submit to the linked block.&lt;/p&gt;  &lt;p&gt;the &lt;strong&gt;broadcast block&lt;/strong&gt; is getting a &lt;strong&gt;Func&amp;lt;T,T&amp;gt; delegate &lt;/strong&gt;as a constructor parameter, the idea behind it is &lt;strong&gt;cloning&lt;/strong&gt; (which will enable separation of the messages).     &lt;br /&gt;if you are passing a &lt;strong&gt;reference type message&lt;/strong&gt; to &lt;strong&gt;multiple agents&lt;/strong&gt;, without cloning, changes that made by one agent will be visible to all the other agents.&lt;/p&gt;  &lt;p&gt;the &lt;strong&gt;broadcast block&lt;/strong&gt; will use the &lt;strong&gt;cloning delegate&lt;/strong&gt; &lt;strong&gt;before sending&lt;/strong&gt; the message to the linked agents.     &lt;br /&gt;the cloning pattern will ensure that only single block is processing a message instance at a time, this will maintain the &lt;strong&gt;message ownership&lt;/strong&gt; and avoid the needs of data synchronization for &lt;strong&gt;thread safety&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;the crawler will use the following block definition for broadcasting:&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:5e9c8188-1ebd-422c-ad5d-b139b99fb104" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#fff;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; contentBroadcaster = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;BroadcastBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt;(s =&amp;gt; s);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;in our case the html content is a string which is immutable, therefore no real cloning is needed.&lt;/p&gt;  &lt;p&gt;the crawler will link the agents (blocks) to each other after the construction of all the relevant blocks, right now we are focusing on the agents themselves.&lt;/p&gt;  &lt;h5&gt;Link parser&lt;/h5&gt;  &lt;p&gt;the link parser is using the following regular expression in order to fetch all the links (&amp;lt;a href=...&amp;quot;/&amp;gt;) out from the html and extract the link&amp;#39;s url.&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:6eaa187b-912d-43d1-be12-7baf5275aa9b" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#fff;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;const&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; LINK_REGEX_HREF = &lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#a31515;"&gt;&amp;quot;&amp;#92;&amp;#92;shref=(&amp;#39;|&amp;#92;&amp;#92;&amp;#92;&amp;quot;)?(?&amp;lt;LINK&amp;gt;http&amp;#92;&amp;#92;://.*?(?=&amp;#92;&amp;#92;1)).*&amp;gt;&amp;quot;&lt;/span&gt;;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Regex&lt;/span&gt; _linkRegexHRef = &lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Regex&lt;/span&gt;(LINK_REGEX_HREF);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;unlike the downloader agent which get a single input (url) and &lt;strong&gt;produce a single output &lt;/strong&gt;(html),     &lt;br /&gt;the &lt;strong&gt;link parser produce multiple outputs&lt;/strong&gt; (links) per each input (html).     &lt;br /&gt;you can use the transform block and set the output type to array of links but the &lt;strong&gt;Tpl Dataflow&lt;/strong&gt; is having a better block for this scenario.     &lt;br /&gt;because the processing of each link is independent of other links, it will be better if the transform output buffer will contain flatten links objects rather then a collection of link&amp;#39;s array.&lt;/p&gt;  &lt;p&gt;the crawler is using the &lt;strong&gt;TransformManyBlock&amp;lt;Tin,Tout&amp;gt;&lt;/strong&gt;. this block is similar to the &lt;strong&gt;transform block&lt;/strong&gt; with only one difference, the delegate at the constructor parameter is one of the following delegates:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Func&amp;lt;Tin, IEnumerable&amp;lt;Tout&amp;gt;&amp;gt;&lt;/strong&gt; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Func&amp;lt;Tin, Task&amp;lt;IEnumerable&amp;lt;Tout&amp;gt;&amp;gt;&amp;gt;&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;the block task will extract the outputs results and put each of the extracted result, separately, in the output buffer.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/image_2F893E2A.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform, IPropagatorBlock" border="0" alt="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform, IPropagatorBlock" src="http://blogs.microsoft.co.il/blogs/bnaya/image_thumb_05C5C337.png" width="499" height="121" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;this is the code for the link parser agent:&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:e4c3ea87-8947-43a6-8b1a-76d3ab8c8455" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#fff;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; linkParser = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;TransformManyBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt;(&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;       (html) =&amp;gt;&lt;/li&gt; &lt;li&gt;       {&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;           &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; output = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt;();&lt;/li&gt; &lt;li&gt;           &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; links = _linkRegexHRef.Matches(html);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;           &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Match&lt;/span&gt; item &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; links)&lt;/li&gt; &lt;li&gt;           {&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;               &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; value = item.Groups[&lt;span style="color:#a31515;"&gt;&amp;quot;LINK&amp;quot;&lt;/span&gt;].Value;&lt;/li&gt; &lt;li&gt;               output.Add(value);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;           }&lt;/li&gt; &lt;li&gt;           &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; output;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;       });&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;it is very straight forward, parse each html by using regex and return list of result which the block will extract into the output buffer.&lt;/p&gt;  &lt;h5&gt;Image parser&lt;/h5&gt;  &lt;p&gt;the image parser is quit similar to the link parser.    &lt;br /&gt;the only differences is that it using different regular expression which extract the image&amp;#39;s url.&lt;/p&gt;  &lt;p&gt;the regex part is:&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:b7393f8c-5e66-4da2-bf4c-3f18ff447c2b" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#fff;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;const&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; IMG_REGEX =&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#a31515;"&gt;&amp;quot;&amp;lt;&amp;#92;&amp;#92;s*img [^&amp;#92;&amp;#92;&amp;gt;]*src=(&amp;#39;|&amp;#92;&amp;quot;)?(?&amp;lt;IMG&amp;gt;http&amp;#92;&amp;#92;://.*?(?=&amp;#92;&amp;#92;1)).*&amp;gt;&amp;#92;&amp;#92;s*([^&amp;lt;]+|.*?)?&amp;#92;&amp;#92;s*&amp;lt;/a&amp;gt;&amp;quot;&lt;/span&gt;;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Regex&lt;/span&gt; _imgRegex =&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Regex&lt;/span&gt;(IMG_REGEX);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;and the parser agent code is:&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:6add4233-6be0-4155-b5f2-2a452e5d6204" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#fff;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; imgParser = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;TransformManyBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt;(&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        (html) =&amp;gt;&lt;/li&gt; &lt;li&gt;        {&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;            &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; output = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt;();&lt;/li&gt; &lt;li&gt;            &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; images = _imgRegex.Matches(html);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;            &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Match&lt;/span&gt; item &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; images)&lt;/li&gt; &lt;li&gt;            {&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;                &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; value = item.Groups[&lt;span style="color:#a31515;"&gt;&amp;quot;IMG&amp;quot;&lt;/span&gt;].Value;&lt;/li&gt; &lt;li&gt;                output.Add(value);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;            }&lt;/li&gt; &lt;li&gt;            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; output;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        });&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;h5&gt;writer agent&lt;/h5&gt;  &lt;p&gt;the last operational agent is the writer agent which will download the an image from a url and save it to the local disk.&lt;/p&gt;  &lt;p&gt;the writer is using a simple &lt;strong&gt;action block&lt;/strong&gt;, which is a simple executer block that have an input buffer and a task.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/image_494D4E8C.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform, IPropagatorBlock" border="0" alt="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform, IPropagatorBlock" src="http://blogs.microsoft.co.il/blogs/bnaya/image_thumb_1B1352D2.png" width="202" height="109" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;the task is fetching messages from the buffer and execute a delegate which is given as constructor parameter.    &lt;br /&gt;the delegate signature can be either &lt;strong&gt;Action&amp;lt;T&amp;gt;&lt;/strong&gt; or &lt;strong&gt;Funk&amp;lt;T, Task&amp;gt;&lt;/strong&gt;. the latter one is great for &lt;strong&gt;IO bound operation&lt;/strong&gt; (from the same reasons discussed earlier when we was looking on the transform block signature).&lt;/p&gt;  &lt;p&gt;because the writer is doing 2 IO bound operations:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;download the image from the web &lt;/li&gt;    &lt;li&gt;write the image to the file system &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;the crawler is using the &lt;strong&gt;Funk&amp;lt;T, Task&amp;gt;&lt;/strong&gt; signature.     &lt;br /&gt;the writer code is:&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:c4c18393-327f-4ebb-b35a-2dfe2d982f02" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#ddd;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; writer = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ActionBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt;(&lt;span style="color:#0000ff;"&gt;async&lt;/span&gt; url =&amp;gt;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;{&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#2b91af;"&gt;WebClient&lt;/span&gt; wc = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;WebClient&lt;/span&gt;();&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#008000;"&gt;// using IOCP the thread pool worker thread does return to the pool&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff;"&gt;byte&lt;/span&gt;[] buffer = &lt;span style="color:#0000ff;"&gt;await&lt;/span&gt; wc.DownloadDataTaskAsync(url);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; fileName = &lt;span style="color:#2b91af;"&gt;Path&lt;/span&gt;.GetFileName(url);&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; name = &lt;span style="color:#a31515;"&gt;@&amp;quot;Images&amp;#92;&amp;quot;&lt;/span&gt; + fileName;&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Stream&lt;/span&gt; srm = &lt;span style="color:#2b91af;"&gt;File&lt;/span&gt;.OpenWrite(name))&lt;/li&gt; &lt;li&gt;    {&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#0000ff;"&gt;await&lt;/span&gt; srm.WriteAsync(buffer, 0, buffer.Length);&lt;/li&gt; &lt;li&gt;    }&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;});&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;the first &lt;strong&gt;await&lt;/strong&gt; at line 5, is awaiting until the task will be &lt;strong&gt;interrupt by the network card&lt;/strong&gt;,     &lt;br /&gt;and the second &lt;strong&gt;await&lt;/strong&gt; at line 12, will await until it will be &lt;strong&gt;interrupt by the file system controller&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;you may have been notice that the second &lt;strong&gt;await&lt;/strong&gt; is within a &lt;strong&gt;using block&lt;/strong&gt;, you can read more about this topic at &lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2012/01/15/using-async-await.aspx" target="_blank"&gt;this&lt;/a&gt; post.&lt;/p&gt;  &lt;h5&gt;link it together&lt;/h5&gt;  &lt;p&gt;right now we are having most of our building blocks and it is time to define the data-flow by linking the block to each other.&lt;/p&gt;  &lt;p&gt;the &lt;strong&gt;downloader&lt;/strong&gt; should be link to the &lt;strong&gt;content broadcaster&lt;/strong&gt; which in tern should be linked both to the &lt;strong&gt;image and link parser&lt;/strong&gt;, the image parser should be linked to the &lt;strong&gt;writer&lt;/strong&gt; and the &lt;strong&gt;link parser&lt;/strong&gt; should be &lt;strong&gt;linked back to the downloader&lt;/strong&gt; (so it can crawl farther).&lt;/p&gt;  &lt;p&gt;but there is one last issue.    &lt;br /&gt;it happens that some web page is having links that is targeting an image. this lead us to more complex linking where the link parser should be linked both to the downloader and having conditional link to the writer for those url that is having an image suffix.     &lt;br /&gt;as we discuss earlier having a direct link from the link parser to both the downloader and the writer will results with starvation of one of those agents.     &lt;br /&gt;we do need a final broadcast block which will handle this distribution task. &lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:dc3b0644-3e5c-4a37-ba0c-1f8cc81b2cdb" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#fff;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; linkBroadcaster = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;BroadcastBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt;(s =&amp;gt; s);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;the &lt;strong&gt;link parser&lt;/strong&gt; will be linked to the &lt;strong&gt;broadcaster&lt;/strong&gt; and the broadcaster will be liked to both the &lt;strong&gt;downloader&lt;/strong&gt; and the &lt;strong&gt;writer&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;we have spoke of the conditional link from the link parser and the writer, but it will be more effective if the link parser to the downloader will be link only those pages that are most likely having useful data like php, aspx, htm, ext...&lt;/p&gt;  &lt;h5&gt;Filtering linked messages&lt;/h5&gt;  &lt;p&gt;the following predicates will be use in order to filter linked messages:&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:0ecb60ad-f394-49fc-b8fb-7505f9c7e164" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#ddd;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#2b91af;"&gt;StringComparison&lt;/span&gt; comparison = &lt;span style="color:#2b91af;"&gt;StringComparison&lt;/span&gt;.InvariantCultureIgnoreCase;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;&lt;span style="color:#2b91af;"&gt;Predicate&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt; linkFilter = link =&amp;gt; &lt;/li&gt; &lt;li&gt;    link.IndexOf(&lt;span style="color:#a31515;"&gt;&amp;quot;.aspx&amp;quot;&lt;/span&gt;, comparison) != -1 ||&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    link.IndexOf(&lt;span style="color:#a31515;"&gt;&amp;quot;.php&amp;quot;&lt;/span&gt;, comparison) != -1 ||&lt;/li&gt; &lt;li&gt;    link.IndexOf(&lt;span style="color:#a31515;"&gt;&amp;quot;.htm&amp;quot;&lt;/span&gt;, comparison) != -1 ||&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    link.IndexOf(&lt;span style="color:#a31515;"&gt;&amp;quot;.html&amp;quot;&lt;/span&gt;, comparison) != -1;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#2b91af;"&gt;Predicate&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;&amp;gt; imgFilter = url =&amp;gt;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    url.EndsWith(&lt;span style="color:#a31515;"&gt;&amp;quot;.jpg&amp;quot;&lt;/span&gt;, comparison) ||&lt;/li&gt; &lt;li&gt;    url.EndsWith(&lt;span style="color:#a31515;"&gt;&amp;quot;.png&amp;quot;&lt;/span&gt;, comparison) ||&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    url.EndsWith(&lt;span style="color:#a31515;"&gt;&amp;quot;.gif&amp;quot;&lt;/span&gt;, comparison);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;the first predicate (line 2) will filter the downloader agent target and the second (line 7) will filter the link parser result which is targeting the writer agent.&lt;/p&gt;  &lt;h5&gt;compose the data-flow&lt;/h5&gt;  &lt;p&gt;finally we got to the agent composition.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/image_1C283BF1.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform, IPropagatorBlock" border="0" alt="TDF, Tpl,Dataflow, ITargerBlock, ISorceBlock, IDataBlobk, Transform, IPropagatorBlock" src="http://blogs.microsoft.co.il/blogs/bnaya/image_thumb_4ADDCEC6.png" width="520" height="407" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:48166a5f-a656-4f62-a6d9-8881c898564e" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#ddd;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#2b91af;"&gt;IDisposable&lt;/span&gt; disposeAll = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;CompositeDisposable&lt;/span&gt;(&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#008000;"&gt;// from [downloader] to [contentBroadcaster]&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    downloader.LinkTo(contentBroadcaster),&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#008000;"&gt;// from [contentBroadcaster] to [imgParser]&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    contentBroadcaster.LinkTo(imgParser),&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#008000;"&gt;// from [contentBroadcaster] to [linkParserHRef]&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    contentBroadcaster.LinkTo(linkParser),&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#008000;"&gt;// from [linkParser] to [linkBroadcaster]&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    linkParser.LinkTo(linkBroadcaster),&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#008000;"&gt;// conditional link to from [linkBroadcaster] to [downloader]&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    linkBroadcaster.LinkTo(downloader, linkFilter, &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;),&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#008000;"&gt;// from [linkBroadcaster] to [writer]&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    linkBroadcaster.LinkTo(writer, imgFilter, &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;),&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#008000;"&gt;// from [imgParser] to [writer]&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    imgParser.LinkTo(writer));&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;each &lt;strong&gt;LinkTo&lt;/strong&gt; operation return a &lt;strong&gt;disposable&lt;/strong&gt; instance which can be use to&lt;strong&gt; dispose the link&lt;/strong&gt; when it no longer needed. the crawler &lt;strong&gt;compose all those disposable&lt;/strong&gt; together into a single disposable called &lt;strong&gt;dispose All&lt;/strong&gt; by using the &lt;strong&gt;CompositeDisposable&lt;/strong&gt; which is part of the &lt;strong&gt;Rx&lt;/strong&gt; library.&lt;/p&gt;  &lt;p&gt;you can see the conditional LinkTo at line 11 and 13.    &lt;br /&gt;is is &lt;strong&gt;very important&lt;/strong&gt; to set the last parameter of the &lt;strong&gt;LinkTo&lt;/strong&gt; to true if you don&amp;#39;t want to dispose the link when the filter doesn&amp;#39;t match the criteria.&lt;/p&gt;  &lt;h5&gt;summary&lt;/h5&gt;  &lt;p&gt;this post was a walkthrough of a web crawler sample.    &lt;br /&gt;the complete sample, which is available in &lt;a href="https://skydrive.live.com/redir.aspx?cid=9bf7c1a515d76a9a&amp;amp;resid=9BF7C1A515D76A9A!1404&amp;amp;parid=9BF7C1A515D76A9A!1321&amp;amp;authkey=!ACW2DtTH6k5CuTk" target="_blank"&gt;here&lt;/a&gt; (VS 11), is also having exception handling, agent termination after x amount of seconds, prevention of processing the same url twice and more. for simplicity the code within this post was a simplified version.&lt;/p&gt;  &lt;br /&gt;&lt;a href="http://dotnetshoutout.com/Tpl-Dataflow-walkthrough-Part-5-Bnaya-Eshet"&gt;&lt;img style="border-right-width:0px;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3A%2F%2Fblogs.microsoft.co.il%2Fblogs%2Fbnaya%2Farchive%2F2012%2F01%2F28%2Ftpl-dataflow-walkthrough-part-5.aspx" /&gt;&lt;/a&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=1000032" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/SELA/default.aspx">SELA</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Parallel/default.aspx">Parallel</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Task/default.aspx">Task</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Thread/default.aspx">Thread</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL/default.aspx">TPL</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Dataflow/default.aspx">Dataflow</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TDF/default.aspx">TDF</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IDataflowBlock/default.aspx">IDataflowBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ISourceBlock/default.aspx">ISourceBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ITargetBlock/default.aspx">ITargetBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/async/default.aspx">async</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/await/default.aspx">await</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL+Dataflow/default.aspx">TPL Dataflow</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TAP/default.aspx">TAP</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/C_2300_5/default.aspx">C#5</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IDataBlobk/default.aspx">IDataBlobk</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ISorceBlock/default.aspx">ISorceBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Transform/default.aspx">Transform</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ITargerBlock/default.aspx">ITargerBlock</category></item><item><title>Tpl Dataflow (IDataflowBlock) - Part 5</title><link>http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/19/tpl-dataflow-idataflowblock-part-5.aspx</link><pubDate>Tue, 20 Dec 2011 01:42:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:961306</guid><dc:creator>bnaya</dc:creator><slash:comments>0</slash:comments><description>&lt;h2&gt;Tpl Dataflow (&lt;strong&gt;IDataflowBlock&lt;/strong&gt; ) - Part 5&lt;/h2&gt;  &lt;p&gt;the previous post discus the concept &lt;strong&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/09/tpl-dataflow-part-2.aspx" target="_blank"&gt;ITargetBlock&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/10/tpl-dataflow-part-3.aspx" target="_blank"&gt;ISourceBlock&lt;/a&gt;,&lt;/strong&gt;     &lt;br /&gt;which is the &lt;strong&gt;TDF&lt;/strong&gt; &lt;strong&gt;consumer/Producer&lt;/strong&gt; contract.&lt;/p&gt;  &lt;p&gt;you can find all the post in this series under the &lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TDF/default.aspx" target="_blank"&gt;TDF&lt;/a&gt; tag. &lt;/p&gt;  &lt;p&gt;this post focus on the &lt;strong&gt;IDataflowBlock&lt;/strong&gt; contract which is the&lt;strong&gt; life-time management&lt;/strong&gt; contract for all data-flow&amp;#39;s blocks.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/MC900238403_048720CC.jpg"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="IDataflowBlock" border="0" alt="IDataflowBlock" src="http://blogs.microsoft.co.il/blogs/bnaya/MC900238403_thumb_3D21A50C.jpg" width="232" height="176" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;the &lt;strong&gt;IDataflowBlock&lt;/strong&gt; define single property and 2 methods:&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:bb71d4ab-5648-4e2b-aa12-4110129aac16" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#ddd;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2em;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IDataflowBlock&lt;/span&gt;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;{&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#2b91af;"&gt;Task&lt;/span&gt; Completion { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; }&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Complete();&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Fault(&lt;span style="color:#2b91af;"&gt;Exception&lt;/span&gt; exception);&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;ending the processing of Dataflow block is done either by calling &lt;strong&gt;Complete&lt;/strong&gt;() or by &lt;strong&gt;Fault&lt;/strong&gt;() in cases that the data flow should exit into fault state.&lt;/p&gt;  &lt;p&gt;in case of &lt;strong&gt;Complete&lt;/strong&gt; the block will finish the processing of all messages that already in it&amp;#39;s inner buffer and decline (&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/09/tpl-dataflow-part-2.aspx" target="_blank"&gt;DecliningPermanently&lt;/a&gt;) any incoming messages.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Fault&lt;/strong&gt;&amp;#160; put the block into faulty state and it does not schedule any messages from its inner buffer.&lt;/p&gt;  &lt;p&gt;the C&lt;strong&gt;ompletion&lt;/strong&gt; property is using the &lt;strong&gt;TAP&lt;/strong&gt; (&lt;font color="#666666"&gt;task asynchrony pattern&lt;/font&gt;) concept as it API for&lt;strong&gt; monitoring the block state&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;the completion property return a &lt;strong&gt;Task&lt;/strong&gt; which enable either &lt;strong&gt;waiting&lt;/strong&gt; (Wait) on, &lt;strong&gt;continuation &lt;/strong&gt;(ContinueWith) or &lt;strong&gt;await&lt;/strong&gt;. &lt;/p&gt;  &lt;p&gt;the block will set the &lt;strong&gt;task completion&lt;/strong&gt; when it will complete the processing of all the messages within it inner buffer (or when finishing current executing messages in case of faulty state).&lt;/p&gt;  &lt;p&gt;because the block is using the &lt;strong&gt;task semantic&lt;/strong&gt; for it&amp;#39;s easy to handle block exceptions.&lt;/p&gt;  &lt;p&gt;the following code demonstrate the management of ActionBlock lifetime.&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:7a04b534-68cf-42ca-991e-ce01eea27d22" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#ddd;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2.5em;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; ab = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ActionBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;&amp;gt;(i =&amp;gt;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;{&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#2b91af;"&gt;Thread&lt;/span&gt;.Sleep(1000);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(i);&lt;/li&gt; &lt;li&gt;});&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;ab.Completion.ContinueWith(t =&amp;gt;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;{&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (t.Status == &lt;span style="color:#2b91af;"&gt;TaskStatus&lt;/span&gt;.Faulted)&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;Failiur: {0}&amp;quot;&lt;/span&gt;, t.Exception);&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;Complete&amp;quot;&lt;/span&gt;);&lt;/li&gt; &lt;li&gt;});&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;Proccesing&amp;quot;&lt;/span&gt;);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;ab.Post(1);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;ab.Post(2);&lt;/li&gt; &lt;li&gt;ab.Post(3);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.ReadKey().KeyChar == &lt;span style="color:#a31515;"&gt;&amp;#39;f&amp;#39;&lt;/span&gt;)&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    (ab &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;IDataflowBlock&lt;/span&gt;).Fault(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Exception&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;wrong tick&amp;quot;&lt;/span&gt;));&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    ab.Complete();&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;at line 7 we have set a continuation callback which check the completion status and writing the completion information.&lt;/p&gt;  &lt;h5&gt;point of interest&lt;/h5&gt;  &lt;p&gt;as we discuss in the previous post the dataflow blocks does have internal task which is responsible for its execution (by default it is one task per block but it can be throttle to work with multiple tasks) this task does release when ever the block become idle (when the block will become active again it will construct new task).&lt;/p&gt;  &lt;p&gt;it is important to understand that the completion task is a semantic task and not one of the worker tasks.&lt;/p&gt;  &lt;p&gt;in case that you want to create you&amp;#39;re own custom block you can use the TaskCompletionSource&amp;lt;T&amp;gt; in order to present the TAP (task asynchrony pattern) semantics.&lt;/p&gt;  &lt;p&gt;you can learn more on the TAP concept in &lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/18/task-thread.aspx" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;h5&gt;Summary&lt;/h5&gt;  &lt;p&gt;every dataflow block implement the IDataflowBlock contract which enable to control and monitor the block life-time.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=961306" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/SELA/default.aspx">SELA</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Parallel/default.aspx">Parallel</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Task/default.aspx">Task</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Thread/default.aspx">Thread</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL/default.aspx">TPL</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Dataflow/default.aspx">Dataflow</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TDF/default.aspx">TDF</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IDataflowBlock/default.aspx">IDataflowBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ISourceBlock/default.aspx">ISourceBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ITargetBlock/default.aspx">ITargetBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL+Dataflow/default.aspx">TPL Dataflow</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TAP/default.aspx">TAP</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/taskcompletionsource/default.aspx">taskcompletionsource</category></item><item><title>Tpl Dataflow (ISourceBlock) - Part 3</title><link>http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/10/tpl-dataflow-part-3.aspx</link><pubDate>Sat, 10 Dec 2011 15:35:42 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:953082</guid><dc:creator>bnaya</dc:creator><slash:comments>0</slash:comments><description>&lt;h2&gt;Tpl Dataflow (ISourceBlock) - Part 3&lt;/h2&gt;  &lt;p&gt;the previous &lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/09/tpl-dataflow-part-2.aspx" target="_blank"&gt;post&lt;/a&gt; discus the concept &lt;strong&gt;ITargetBlock&lt;/strong&gt;     &lt;br /&gt;which is the &lt;strong&gt;TDF&lt;/strong&gt; &lt;strong&gt;consumer&lt;/strong&gt; contract.&lt;/p&gt;  &lt;p&gt;this post will focus on the &lt;strong&gt;source block&lt;/strong&gt; which is the &lt;strong&gt;producer&lt;/strong&gt; contract.&lt;/p&gt;  &lt;p&gt;as mention in previous post, &lt;strong&gt;sources&lt;/strong&gt; and &lt;strong&gt;targets&lt;/strong&gt; engage in a protocol for transferring messages between them.&lt;/p&gt;  &lt;p&gt;&lt;a title="ISourceBlock, TDF" href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/09/tpl-dataflow-part-2.aspx"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="manufacture_small" border="0" alt="manufacture_small" src="http://blogs.microsoft.co.il/blogs/bnaya/manufacture_small_24AD2275.png" width="244" height="135" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;Source Block:&lt;/h4&gt;  &lt;p&gt;the &lt;strong&gt;source block&lt;/strong&gt; main responsibility is to produce (or manipulate) data which will be &lt;strong&gt;consume&lt;/strong&gt; by the &lt;strong&gt;target&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;as we learn in &lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/09/tpl-dataflow-part-2.aspx" target="_blank"&gt;previous post&lt;/a&gt; the target may consume the data either directly (&lt;strong&gt;push&lt;/strong&gt;) or indirectly (&lt;strong&gt;pull&lt;/strong&gt;).&lt;/p&gt;  &lt;p&gt;a target can be attached to source using the &lt;strong&gt;ISourceBlock&amp;lt;T&amp;gt;&lt;/strong&gt; LinkTo method :&lt;/p&gt;  &lt;h5&gt;&lt;strong&gt;LinkTo:&lt;/strong&gt;&lt;/h5&gt;  &lt;p&gt;link to provide the ability to &lt;strong&gt;link&lt;/strong&gt; one or more &lt;strong&gt;targets &lt;/strong&gt;to a &lt;strong&gt;source&lt;/strong&gt;, this is how we can build a Dataflow network.     &lt;br /&gt;when target is linked to sources the sources automatically propagate any data they contain to targets (asynchronously upon the source distribution strategy).&lt;/p&gt;  &lt;h5&gt;Detaching linked target from a source:&lt;/h5&gt;  &lt;p&gt;the LinkTo method returns a &lt;strong&gt;IDisposable&lt;/strong&gt; which can be use to detach the target from the source (at nay time).&lt;/p&gt;  &lt;h5&gt;Dataflow network:&lt;/h5&gt;  &lt;p&gt;actually we can &lt;strong&gt;dynamically&lt;/strong&gt; change the &lt;strong&gt;Dataflow network&lt;/strong&gt; at runtime while attaching and detaching blocks.&lt;/p&gt;  &lt;h5&gt;Pull:&lt;/h5&gt;  &lt;p&gt;When &lt;strong&gt;source push&lt;/strong&gt; data to a &lt;strong&gt;target&lt;/strong&gt;, the protocol employed may allow the &lt;strong&gt;target&lt;/strong&gt; to simply &lt;strong&gt;accept&lt;/strong&gt; and take ownership on the offered data, or it may require the &lt;strong&gt;target&lt;/strong&gt; to &lt;strong&gt;communicate&lt;/strong&gt; &lt;strong&gt;back&lt;/strong&gt; to the &lt;strong&gt;source &lt;/strong&gt;(pull).&lt;/p&gt;  &lt;p&gt;see the &lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/12/09/tpl-dataflow-part-2.aspx"&gt;previous post&lt;/a&gt; for more details.&lt;/p&gt;  &lt;h6&gt;Race condition:&lt;/h6&gt;  &lt;p&gt;when a &lt;strong&gt;target&lt;/strong&gt; is &lt;strong&gt;pulling&lt;/strong&gt; data out of &lt;strong&gt;one&lt;/strong&gt; &lt;strong&gt;or more sources&lt;/strong&gt; it may have to ensure that the data does not simultaneously consumed by other targets.     &lt;br /&gt;it is getting even more complicate when a &lt;strong&gt;target&lt;/strong&gt; try to &lt;strong&gt;atomically consume messages&lt;/strong&gt; from multiple sources (which mean either succeeding to consume all messages on none). &lt;/p&gt;  &lt;h5&gt;Two-phase commit:&lt;/h5&gt;  &lt;p&gt;by using the &lt;strong&gt;two-phase commit&lt;/strong&gt; protocol the target can &lt;strong&gt;atomically consume multiple messages&lt;/strong&gt; (&lt;font color="#666666"&gt;from one or more sources&lt;/font&gt;).&lt;/p&gt;  &lt;p&gt;the &lt;strong&gt;ISourceBlock&amp;lt;T&amp;gt;&lt;/strong&gt; define the following methods in order to enable two-phase commit protocol:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ConsumeMeassage (commit) &lt;/li&gt;    &lt;li&gt;ReserveMessage (prepare) &lt;/li&gt;    &lt;li&gt;ReleaseMessage (roll-back) &lt;/li&gt; &lt;/ul&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:0a5462c5-3871-41a7-8bdb-bcd620ddc48c" class="wlWriterEditableSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#fff;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ISourceBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; TOutput&amp;gt; : IDataflowBlock&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;{&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#2b91af;"&gt;IDisposable&lt;/span&gt; LinkTo(&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#2b91af;"&gt;ITargetBlock&lt;/span&gt;&amp;lt;TOutput&amp;gt; target, &lt;/li&gt; &lt;li&gt;        &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; unlinkAfterOne);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;    TOutput ConsumeMessage(&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#2b91af;"&gt;DataflowMessageHeader&lt;/span&gt; messageHeader, &lt;/li&gt; &lt;li&gt;        &lt;span style="color:#2b91af;"&gt;ITargetBlock&lt;/span&gt;&amp;lt;TOutput&amp;gt; target, &lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#0000ff;"&gt;out&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; messageConsumed);&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; ReserveMessage(&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#2b91af;"&gt;DataflowMessageHeader&lt;/span&gt; messageHeader, &lt;/li&gt; &lt;li&gt;        &lt;span style="color:#2b91af;"&gt;ITargetBlock&lt;/span&gt;&amp;lt;TOutput&amp;gt; target);&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;    &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; ReleaseReservation(&lt;/li&gt; &lt;li&gt;        &lt;span style="color:#2b91af;"&gt;DataflowMessageHeader&lt;/span&gt; messageHeader, &lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;        &lt;span style="color:#2b91af;"&gt;ITargetBlock&lt;/span&gt;&amp;lt;TOutput&amp;gt; target);&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;h6&gt;Two-phase commit in action:&lt;/h6&gt;  &lt;p&gt;when target want to atomically consume messages from one or more sources:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;it try to &lt;strong&gt;reserve&lt;/strong&gt; the messages on each source (&lt;font color="#666666"&gt;the message header has the message identifier&lt;/font&gt;). &lt;/li&gt;    &lt;li&gt;if it &lt;strong&gt;failed to reserve&lt;/strong&gt; one of the messages, it should release other reservation using &lt;strong&gt;ReleaseResarvation&lt;/strong&gt; (roll back). &lt;/li&gt;    &lt;li&gt;if all &lt;strong&gt;reservation succeed&lt;/strong&gt; it can safely consume the messages, using &lt;strong&gt;ConsumeMessage&lt;/strong&gt; (commit). &lt;/li&gt; &lt;/ol&gt;  &lt;h5&gt;Consume Message:&lt;/h5&gt;  &lt;p&gt;even without two-phase commit, the &lt;strong&gt;ConsumeMessage&lt;/strong&gt; design to &lt;strong&gt;handle race condition&lt;/strong&gt;.     &lt;br /&gt;when ever we call the consume message, the source block assign the consume message&amp;#39;s &lt;strong&gt;messageConsumed&lt;/strong&gt; out parameter to indicate whether the consume operation has succeed. this way the source can ensure that the message will be consume by a single target and avoid race conditions.&lt;/p&gt;  &lt;h5&gt;Summary&lt;/h5&gt;  &lt;p&gt;using the &lt;strong&gt;TDF&lt;/strong&gt; source and target contract we can apply push and pulling strategy while avoiding race condition.&lt;/p&gt;  &lt;p&gt;&lt;font color="#666666"&gt;in the following posts I will speak about the blocks house keeping contract and propagating&lt;/font&gt;.&lt;/p&gt;  &lt;br /&gt;&lt;a href="http://dotnetshoutout.com/Tpl-Dataflow-Part-3-Bnaya-Eshet"&gt;&lt;img style="border-right-width:0px;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3A%2F%2Fblogs.microsoft.co.il%2Fblogs%2Fbnaya%2Farchive%2F2011%2F12%2F10%2Ftpl-dataflow-part-3.aspx" /&gt;&lt;/a&gt; &lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fbnaya%2farchive%2f2011%2f12%2f10%2ftpl-dataflow-part-3.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fbnaya%2farchive%2f2011%2f12%2f10%2ftpl-dataflow-part-3.aspx" /&gt;&lt;/a&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=953082" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/SELA/default.aspx">SELA</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Task/default.aspx">Task</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL/default.aspx">TPL</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Dataflow/default.aspx">Dataflow</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TDF/default.aspx">TDF</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IDataflowBlock/default.aspx">IDataflowBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ISourceBlock/default.aspx">ISourceBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ITargetBlock/default.aspx">ITargetBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL+Dataflow/default.aspx">TPL Dataflow</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TAP/default.aspx">TAP</category></item><item><title>SDP Agenda - TPL and Beyond</title><link>http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/11/30/sdp-agenda-tpl-and-beyond.aspx</link><pubDate>Thu, 01 Dec 2011 01:13:46 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:944395</guid><dc:creator>bnaya</dc:creator><slash:comments>0</slash:comments><description>&lt;h2&gt;SDP Agenda - TPL and Beyond&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/SDP_7C019EE3.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="SDP" border="0" alt="SDP" src="http://blogs.microsoft.co.il/blogs/bnaya/SDP_thumb_774B488F.png" width="409" height="105" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;the SDP conference is taking place next week   &lt;br /&gt;and we have close the final agenda.&lt;/p&gt;  &lt;p&gt;the first day (&lt;a href="http://www.sela.co.il/s/SDP/Dec2011/tutorials2.html#d73"&gt;Introduction to TPL&lt;/a&gt;) will include:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;TPL introduction&lt;/li&gt;    &lt;li&gt;What&amp;#39;s new in TPL 4.5&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;the second day (&lt;a href="http://www.sela.co.il/s/SDP/Dec2011/tutorials2.html#d83"&gt;Parallel Programming: One Step Beyond&lt;/a&gt;) will include:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Async (new syntax for .NET 4.5)&lt;/li&gt;    &lt;li&gt;Rx - Reactive Extension &lt;/li&gt;    &lt;li&gt;TPL Dataflow&lt;/li&gt; &lt;/ul&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=944395" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/SELA/default.aspx">SELA</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Rx/default.aspx">Rx</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IObserver/default.aspx">IObserver</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Reactive+Extensions/default.aspx">Reactive Extensions</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IObservable/default.aspx">IObservable</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Task/default.aspx">Task</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL/default.aspx">TPL</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IQbservable/default.aspx">IQbservable</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IDataflowBlock/default.aspx">IDataflowBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ISourceBlock/default.aspx">ISourceBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IScheduler/default.aspx">IScheduler</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/SDP/default.aspx">SDP</category></item><item><title>Rx - User Group session</title><link>http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/11/22/rx-user-group-session.aspx</link><pubDate>Tue, 22 Nov 2011 13:28:36 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:937599</guid><dc:creator>bnaya</dc:creator><slash:comments>0</slash:comments><description>&lt;h2&gt;Rx - User Group session&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/rx_05196783.jpg"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="rx" border="0" alt="rx" src="http://blogs.microsoft.co.il/blogs/bnaya/rx_thumb_5C4DDC6C.jpg" width="464" height="109" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;this is just a reminder,    &lt;br /&gt;tomorrow (Wednesday 2011-11-22)    &lt;br /&gt;I&amp;#39;m giving Rx (Reactive Extension) session at Microsoft Israel user group.&lt;/p&gt;  &lt;p&gt;if you want to hear about Rx you can register at &lt;a href="http://isrmsdn-net-nov2011.eventbrite.com/" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/sasha/image_6438F214.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;border-top:0px;border-right:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/sasha/image_thumb_4DB62DC0.png" width="536" height="135" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;on the other hand if you want a full day tutorial on TPL 4.5 you can resister to &lt;a href="http://www.sela.co.il/s/SDP/Dec2011/index.html"&gt;Sela Developer Practice&lt;/a&gt; (this one is not for free).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/roadan" target="_blank"&gt;Yaniv Rodenski&lt;/a&gt; and I will give 2 days tutorials about TPL and Async programing in .NET 4.5.&lt;/p&gt;  &lt;p&gt;the first day is a walk through TPL 4 and the new async and await keywords of .NET 4.5.&lt;/p&gt;  &lt;p&gt;and the second day will focus on what&amp;#39;s new in TPL 4.5, TPL Dataflow and Rx (Reactive Extension).&lt;/p&gt;  &lt;p&gt;the agenda still may slightly shift but you should be aware that the second day assume deep understanding of TPL 4, therefore it is very recommended to have both the first and second day. &lt;/p&gt;  &lt;p&gt;if you can only attend one day and you don&amp;#39;t have real solid understanding and practice in TPL 4, I recommend the first day over the second.   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4db750c7-5e9a-48a8-9926-dd871fe1ad28" class="wlWriterEditableSmartContent"&gt;del.icio.us Tags: &lt;a href="http://del.icio.us/popular/TPL" rel="tag"&gt;TPL&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/Rx" rel="tag"&gt;Rx&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/Dataflow" rel="tag"&gt;Dataflow&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/Sela" rel="tag"&gt;Sela&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/IObservable" rel="tag"&gt;IObservable&lt;/a&gt;,&lt;a href="http://del.icio.us/popular/IObserver" rel="tag"&gt;IObserver&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=937599" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/SELA/default.aspx">SELA</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Rx/default.aspx">Rx</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IObserver/default.aspx">IObserver</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Parallel/default.aspx">Parallel</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IObservable/default.aspx">IObservable</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Task/default.aspx">Task</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL/default.aspx">TPL</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IQbservable/default.aspx">IQbservable</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Dataflow/default.aspx">Dataflow</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IDataflowBlock/default.aspx">IDataflowBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ITarget/default.aspx">ITarget</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/async/default.aspx">async</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ISource/default.aspx">ISource</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/await/default.aspx">await</category></item><item><title>Tpl Dataflow - User Group</title><link>http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/08/17/tpl-dataflow-user-group.aspx</link><pubDate>Thu, 18 Aug 2011 03:02:13 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:885777</guid><dc:creator>bnaya</dc:creator><slash:comments>0</slash:comments><description>&lt;h2&gt;Tpl Dataflow - User Group&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/image_62EC32E51_4AD402EE.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Tpl dataflow, ISourceBlock, ITargetblock" border="0" alt="Tpl dataflow, ISourceBlock, ITargetblock" src="http://blogs.microsoft.co.il/blogs/bnaya/image_62EC32E51_thumb_0663EBE2.png" width="111" height="81" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Today I was lecturing at &lt;strong&gt;Microsoft User Group &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;about the new &lt;strong&gt;TPL Dataflow&lt;/strong&gt; (&lt;strong&gt;TDF&lt;/strong&gt;) library.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;first I want to thanks all attendants. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I will post about more aspects of the &lt;strong&gt;Tpl Dataflow&lt;/strong&gt; in future posts. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;the presentation and code samples, &lt;/p&gt;  &lt;p&gt;available for download from &lt;a href="https://p6efwa.blu.livefilestore.com/y1p04lMRjWxX1uj_WvPx4XgG7GSXM2wduQ2tyi-pFndRqIzaUln1LOJrY-ZXvEQxuTCw9v75jj02OX7MHXX4c0gLQ/Tpl%20Dataflow.pdf?download&amp;amp;psid=1" target="_blank"&gt;here&lt;/a&gt; and &lt;a href="https://p6efwa.blu.livefilestore.com/y1pNc8__dEm2XuCk9lq-FQVPmq7cYxjH2MqUy96HEbWt8iVHNNEEUBIpVvqHaHu9vh2DgYdg291Twfi323Sf86hsQ/TPL%20Dataflow%20code.zip?download&amp;amp;psid=1" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="https://p6efwa.blu.livefilestore.com/y1p04lMRjWxX1uj_WvPx4XgG7GSXM2wduQ2tyi-pFndRqIzaUln1LOJrY-ZXvEQxuTCw9v75jj02OX7MHXX4c0gLQ/Tpl%20Dataflow.pdf?download&amp;amp;psid=1" target="_blank"&gt;download&lt;/a&gt; pdf.&lt;/p&gt;  &lt;p&gt;&lt;a href="https://p6efwa.blu.livefilestore.com/y1pNc8__dEm2XuCk9lq-FQVPmq7cYxjH2MqUy96HEbWt8iVHNNEEUBIpVvqHaHu9vh2DgYdg291Twfi323Sf86hsQ/TPL%20Dataflow%20code.zip?download&amp;amp;psid=1" target="_blank"&gt;download&lt;/a&gt; code samples.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="text-align:right;margin:0px;padding:4px 0px 4px 0px;"&gt;&lt;a href="http://digg.com/submit?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fbnaya%2farchive%2f2011%2f08%2f17%2ftpl-dataflow-user-group.aspx&amp;amp;title=Tpl+Dataflow+-+User+Group"&gt;&lt;img src="http://digg.com/img/badges/100x20-digg-button.png" width="100" height="20" alt="Digg This" title="Digg This" border="0" style="border:0;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=885777" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/SELA/default.aspx">SELA</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Parallel/default.aspx">Parallel</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Task/default.aspx">Task</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL/default.aspx">TPL</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Dataflow/default.aspx">Dataflow</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TDF/default.aspx">TDF</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IDataflowBlock/default.aspx">IDataflowBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ISourceBlock/default.aspx">ISourceBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ITargetBlock/default.aspx">ITargetBlock</category></item><item><title>Tpl Dataflow - Part 1</title><link>http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/08/02/tpl-dataflow-part-1.aspx</link><pubDate>Tue, 02 Aug 2011 18:57:56 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:879034</guid><dc:creator>bnaya</dc:creator><slash:comments>0</slash:comments><description>&lt;h2&gt;Tpl Dataflow - Part 1&lt;/h2&gt;  &lt;p&gt;this post is the first of post series which will focus&lt;/p&gt;  &lt;p&gt;on the new &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/devlabs/gg585582" target="_blank"&gt;Tpl Dataflow library&lt;/a&gt;&lt;/strong&gt; (&lt;strong&gt;TDF&lt;/strong&gt;).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/image_62EC32E5.png"&gt;&lt;img style="border-right-width:0px;margin:0px 10px 0px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Tpl, Tpl dataflow, Task, ActionBlock, high-throughput , low-latency" border="0" alt="Tpl, Tpl dataflow, Task, ActionBlock, high-throughput , low-latency" align="left" src="http://blogs.microsoft.co.il/blogs/bnaya/image_thumb_190DAB35.png" width="110" height="78" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;TDF&lt;/strong&gt; goal is to address &lt;strong&gt;high-throughput&lt;/strong&gt; / &lt;strong&gt;low-latency&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;flow scenario of &lt;strong&gt;complex computing&lt;/strong&gt; / &lt;strong&gt;IO intensive&lt;/strong&gt; / &lt;strong&gt;immense traffic&lt;/strong&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The library is using a few basic &lt;strong&gt;buffering&lt;/strong&gt; and &lt;strong&gt;message&lt;/strong&gt; base pattern in order to&lt;/p&gt;  &lt;p&gt;enable basic block which can be compose together into full scale scenario.&lt;/p&gt;  &lt;p&gt;each building block construct as &lt;strong&gt;agent&lt;/strong&gt; which have internal buffer and execution management.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;one of the most simple block is the &lt;strong&gt;ActionBlock:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/bnaya/image_33016B57.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Tpl, Tpl dataflow, Task, ActionBlock" border="0" alt="Tpl, Tpl dataflow, Task, ActionBlock" src="http://blogs.microsoft.co.il/blogs/bnaya/image_thumb_0FF0F9E7.png" width="411" height="133" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;each time item is send into the ActionBlock it will be buffer in&lt;/p&gt;  &lt;p&gt;the internal buffer, than the Block Task will take &lt;/p&gt;  &lt;p&gt;one item at a-time and will process it.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#808080"&gt;by default the ActionBlock schedule only single Task at a-time,&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#808080"&gt;but latter on this &lt;/font&gt;&lt;font color="#808080"&gt;series&amp;#160; we will see that this default can be change. &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#808080"&gt;actually the Block release Its Task &lt;/font&gt;&lt;font color="#808080"&gt;whenever the buffer become empty.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:02083b6f-0a13-44eb-8839-387da849d74c" class="wlWriterSmartContent"&gt; &lt;div style="border:#000080 1px solid;color:#000;font-family:&amp;#39;Courier New&amp;#39;, Courier, Monospace;font-size:10pt;"&gt; &lt;div style="background:#000080;color:#fff;font-family:Verdana, Tahoma, Arial, sans-serif;font-weight:bold;padding:2px 5px;"&gt;Code Snippet&lt;/div&gt; &lt;div style="background:#ddd;overflow:auto;"&gt; &lt;ol style="background:#ffffff;margin:0 0 0 2em;padding:0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; ab = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;ActionBlock&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;&amp;gt;(i =&amp;gt; &lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.Write(i));&lt;/li&gt; &lt;li style="background:#f3f3f3;"&gt;&lt;span style="color:#2b91af;"&gt;Parallel&lt;/span&gt;.For(0, 1000, i =&amp;gt; ab.Post(i));&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;as we can see the ActionBlock syntax can be very simple.&lt;/p&gt;  &lt;p&gt;it define an action (&lt;font color="#808080"&gt;in the above case Console.Write&lt;/font&gt;) and it can fed with data, &lt;font color="#808080"&gt;ab.Post(i)&lt;/font&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h5&gt;Summary&lt;/h5&gt;  &lt;p&gt;ActionBlock is one of the simplest block.&lt;/p&gt;  &lt;p&gt;in the future post we will survey other blocks, TDF interfaces, blocks overloads and concepts,&lt;/p&gt;  &lt;p&gt;we will see how to chain blocks in a row, and we will &lt;/p&gt;  &lt;p&gt;discuss some of the architecture decisions.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h5&gt;Point Of Interest:&lt;/h5&gt;  &lt;p&gt;My lecture on this topic at Microsoft User group has change to 2011-08-17.&lt;/p&gt;  &lt;p&gt;you can register using this &lt;a href="https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032490936&amp;amp;Culture=he-IL" target="_blank"&gt;link&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;a href="http://dotnetshoutout.com/Tpl-Dataflow-Part-1-Export-Bnaya-Eshet"&gt;&lt;img style="border-right-width:0px;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3A%2F%2Fblogs.microsoft.co.il%2Fblogs%2Fbnaya%2Farchive%2F2011%2F08%2F02%2Ftpl-dataflow-part-1.aspx" /&gt;&lt;/a&gt; &lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fbnaya%2farchive%2f2011%2f08%2f02%2ftpl-dataflow-part-1.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fbnaya%2farchive%2f2011%2f08%2f02%2ftpl-dataflow-part-1.aspx" /&gt;&lt;/a&gt;&lt;div class="wlWriterHeaderFooter" style="text-align:right;margin:0px;padding:4px 0px 4px 0px;"&gt;&lt;a href="http://digg.com/submit?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fbnaya%2farchive%2f2011%2f08%2f02%2ftpl-dataflow-part-1.aspx&amp;amp;title=Tpl+Dataflow+-+Part+1"&gt;&lt;img src="http://digg.com/img/badges/100x20-digg-button.png" width="100" height="20" alt="Digg This" title="Digg This" border="0" style="border:0;" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=879034" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/SELA/default.aspx">SELA</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Task/default.aspx">Task</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TPL/default.aspx">TPL</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/Dataflow/default.aspx">Dataflow</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/TDF/default.aspx">TDF</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/IDataflowBlock/default.aspx">IDataflowBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ISourceBlock/default.aspx">ISourceBlock</category><category domain="http://blogs.microsoft.co.il/blogs/bnaya/archive/tags/ITargetBlock/default.aspx">ITargetBlock</category></item></channel></rss>