{"id":55961,"date":"2009-11-05T19:44:00","date_gmt":"2009-11-05T19:44:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2009\/11\/05\/whats-new-for-the-coordination-data-structures-in-beta-2\/"},"modified":"2009-11-05T19:44:00","modified_gmt":"2009-11-05T19:44:00","slug":"whats-new-for-the-coordination-data-structures-in-beta-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/whats-new-for-the-coordination-data-structures-in-beta-2\/","title":{"rendered":"What\u2019s new for the coordination data structures in Beta 2?"},"content":{"rendered":"<p><P>Rejoice!&nbsp; Visual Studio 2010 Beta 2 is upon us and it includes lots of great changes for the Parallel Extensions.&nbsp; TPL guru Danny Shih has already covered <A href=\"https:\/\/blogs.msdn.com\/pfxteam\/archive\/2009\/10\/19\/9909371.aspx\">what\u2019s new in TPL<\/A> and PLINQ aficionado Ed Essey has <A href=\"https:\/\/blogs.msdn.com\/pfxteam\/archive\/2009\/11\/05\/9918226.aspx\">covered the best way to use LINQ<\/A> (specifically between Beta 1 and Beta 2) but your favorite set of thread-safe collections and synchronization primitives are in on the action too.&nbsp; <\/P>\n<P>So what\u2019s changed?&nbsp; Overall, we\u2019ve been fixing bugs, of course, but we\u2019ve also spent a lot of time fine-tuning these types to get the best performance possible.&nbsp; That said, performance varies greatly from architecture to architecture and from scenario to scenario, so make sure you stick on your detective hat, fire up the <A href=\"https:\/\/channel9.msdn.com\/posts\/philpenn\/Concurrent-Visualization-Techniques-in-the-VS2010-Profiler\/\" target=\"_blank\">Concurrency Visualizer<\/A> and go sleuthing around your app\u2019s performance profile to ensure that you\u2019re using the right types in the right way.&nbsp; We\u2019re always happy to see perf results and field perf-related questions on <A href=\"http:\/\/social.msdn.microsoft.com\/Forums\/en-US\/parallelextensions\/threads\" target=\"_blank\">our forum<\/A>.<\/P>\n<P>I\u2019m not going to talk about specific bugs or perf improvements here but let\u2019s jump into functionality that\u2019s been added or changed:<\/P>\n<P><STRONG>Barrier <BR><\/STRONG>In Beta 1, Barrier used to track phase numbers using a 32-bit integer.&nbsp; While most scenarios for Barrier couldn\u2019t conceive of exhausting a range of 4+ billion numbers, for long running services, it\u2019s not infeasible.&nbsp; That\u2019s why we\u2019ve decided to change Barrier to track phases using a 64-bit integer (so check for any code that called AddParticipant{s} or CurrentPhaseNumber).&nbsp; We encourage you to take comfort in the fact that your tasks and threads can joyously join together in cyclic fashion for an eternity*.&nbsp; <\/P>\n<P>Also, in previous releases, if you decided to give Barrier a Post Phase Action to execute when all threads completed a phase, any exceptions thrown from that action would be thrown unwrapped and only on the thread that actually ended up executing the action.&nbsp; We\u2019ve since realized that that\u2019s a little silly.&nbsp; If your Post Phase Action faulted, more than likely, your algorithm is corrupt but only one thread would know about it.&nbsp; In Beta 2, <EM>all<\/EM> of your threads participating in a Barrier are now privy to these kinds of failures: any exceptions thrown from your action are wrapped in a BarrierPostPhaseException and thrown on all the threads that participated in that phase. <\/P>\n<P><FONT size=\"1\">*Not really an eternity. A really really long time though.&nbsp; <\/FONT><\/P>\n<P><STRONG>BlockingCollection&lt;T&gt; <BR><\/STRONG>Good ol\u2019 blocking collection. It\u2019s giving producer threads and consumer threads everywhere a common ground upon which to communicate and brimming with thread-safety at every API.&nbsp; What\u2019s that you say?&nbsp; In Beta 1 BlockingCollection&lt;T&gt;.Add() and BlockingCollection&lt;T&gt;.CompleteAdding() were not thread-safe with respect to each other?&nbsp; Using them concurrently might\u2019ve corrupted the data structure so in Beta 1 you couldn\u2019t do something like a nice parallel graph-traversal?<\/P><PRE class=\"csharpcode\">var targetNode = \u2026;\nvar bc = <SPAN class=\"kwrd\">new<\/SPAN> BlockingCollection&lt;Node&gt;(startingNodes);<BR><FONT color=\"#00b75b\">\/\/ since we expect GetConsumingEnumerable to block, limit parallelism to the number of<BR>\/\/ procs, avoiding too much thread injection<\/FONT><BR>var parOpts = new ParallelOptions() { MaxDegreeOfParallelism = Enivronment.ProcessorCount };\nParallel.ForEach(bc.GetConsumingEnumerable(), parOpts, (node,loop) =&gt;\n{\n    <SPAN class=\"kwrd\">if<\/SPAN> (node == targetNode)\n    {\n        Console.WriteLine(\u201chooray!\u201d);\n        bc.CompleteAdding();\n        loop.Stop();\n    }\n    <SPAN class=\"kwrd\">else<\/SPAN>\n    {\n        <SPAN class=\"kwrd\">foreach<\/SPAN>(var neighbor <SPAN class=\"kwrd\">in<\/SPAN> node.Neighbors) bc.Add(neighbor);\n    }\n});<\/PRE>\n<P>Well worry no longer.&nbsp; Our team of concurrency-geniuses has crammed even <EM>more<\/EM> thread-safety into BlockingCollection&lt;T&gt; for your graph-traversing pleasure by making these two methods thread-safe. (Note that Add() will now throw an exception if called after CompleteAdding() has been called so with Beta 2, you\u2019ll need to put a catch block around the call to Add in this example.)<\/P>\n<P><STRONG>ConcurrentDictionary&lt;TKey,TValue&gt;<\/STRONG> <BR>Since Beta 1 has released, we\u2019ve gotten a lot of feedback, both internal and external, about ConcurrentDictionary&lt;TKey,TValue&gt;.&nbsp; CD is slightly more special than the other concurrent collections added in .NET 4: unlike the other collections, it provides direct access to all of it\u2019s elements.&nbsp; This, of course, supports a whole different set of scenarios.&nbsp; While ConcurrentStack&lt;T&gt;, ConcurrentQueue&lt;T&gt;, and ConcurrentBag&lt;T&gt; are really about processing arbitrary elements, ConcurrentDictionary&lt;TKey,TValue&gt; is about processing elements associated with known keys.&nbsp; With the former, threads will only race on access to the end elements of the collection.&nbsp; With the latter, access to every element may result in a race.&nbsp; That said, in Beta 1, it was very difficult to do any multi-step operations with the elements in a ConcurrentDictionary&lt;TKey,TValue&gt;.&nbsp; Suppose you just wanted to create a simple thread-safe cache.&nbsp; You were forced to check if the value existed and add it if it did not. Of course, in the time between checking for the item and adding it, an element with the same key could have been added, forcing you to check for such a condition and trying again.&nbsp; <\/P>\n<P>Enter two new atomic multi-step operations* on CD: GetOrAdd and AddOrUpdate.<\/P>\n<P>GetOrAdd allows you to specify a key as well as a value (or delegate to produce the value). The method will atomically check for the existence of a given key and, if the key already exists, return the existing value.&nbsp; If the key does not exist, this method will add the new value you\u2019ve specified (with or without the delegate).&nbsp; For example:<\/P><PRE class=\"csharpcode\"><SPAN class=\"kwrd\">private<\/SPAN> ConcurrentDictionary&lt;<SPAN class=\"kwrd\">string<\/SPAN>, Data&gt; _cache = \n    <SPAN class=\"kwrd\">new<\/SPAN> ConcurrentDictionary&lt;<SPAN class=\"kwrd\">string<\/SPAN>,Data&gt;();<\/p>\n<p><SPAN class=\"rem\">\/\/ on multiple threads<\/SPAN>\n<SPAN class=\"kwrd\">public<\/SPAN> Data ProcessRequest(<SPAN class=\"kwrd\">string<\/SPAN> input)\n{\n    <SPAN class=\"kwrd\">return<\/SPAN> _cache.GetOrAdd(input, (key) =&gt;\n    {\n         &#8230;;\n         <SPAN class=\"kwrd\">return<\/SPAN> &#8230;;\n    }    \n}<\/PRE><\/p>\n<p>.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, &#8220;Courier New&#8221;, courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/p>\n<p><P>AddOrUpdate enables you to either add a new element at a given key or update an existing one if that key already exists, great for scenarios that need thread-safe lookup-tables like counting the number of occurrences of a given string in parallel:<\/P><PRE class=\"csharpcode\"><SPAN class=\"kwrd\">private<\/SPAN> ConcurrentDictionary&lt;<SPAN class=\"kwrd\">string<\/SPAN>,<SPAN class=\"kwrd\">int<\/SPAN>&gt; _counts = \n    <SPAN class=\"kwrd\">new<\/SPAN> ConcurrentDictionary&lt;<SPAN class=\"kwrd\">string<\/SPAN>,<SPAN class=\"kwrd\">int<\/SPAN>&gt;();<\/p>\n<p><SPAN class=\"rem\">\/\/ on multiple threads<\/SPAN>\n<SPAN class=\"kwrd\">public<\/SPAN> <SPAN class=\"kwrd\">int<\/SPAN> CountRequest(<SPAN class=\"kwrd\">string<\/SPAN> input)\n{\n    <SPAN class=\"kwrd\">return<\/SPAN> _counts.AddOrUpdate(input, 1, (key,old) =&gt; old + 1);\n}<\/PRE><\/p>\n<p>.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, &#8220;Courier New&#8221;, courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }<\/p>\n<p><P>With AddOrUpdate, you specify the key that you\u2019re interested in, the value to add if the key is not present (or a delegate to create that value), and, finally, a delegate that will generate the new value in the case that the key is already present.&nbsp; This delegate passes along the key and existing value key so your delegate can use it to determine the new value.&nbsp; <\/P>\n<P>Nifty!<\/P>\n<P>*Atomic with regards to other mutating methods on the collection (e.g. TryAdd\/TryUpdate\/TryRemove\/etc.), excluding the execution of the user-provided delegate.&nbsp; This means that if multiple threads race to call GetOrAdd all of their delegates may be called and some delegates may be called multiple times. Users are expected to rollback any unwanted side-effects.<\/P>\n<P><STRONG>ConcurrentLinkedList&lt;T&gt; and ConcurrentLinkedListNode&lt;T&gt; <BR><\/STRONG>In each and every software professional\u2019s career there comes a point where he or she might have to swallow their pride and let a creation that they love go.&nbsp; For some reason or another, their fancy invention just ultimately, doesn\u2019t provide enough value to justify its existence.&nbsp; Now I know we went and got you all excited about ConcurrentLinkedList&lt;T&gt; in Beta 1 but we had to let it go (we did warn you though!).&nbsp; Unfortunately, with the time we had available we just couldn\u2019t get it to be usable <EM>and<\/EM> perform well.&nbsp; There seem to be many thread-safe linked list implementations that are very scalable but usually that scalability is based on some assumption or odd caveat in the design that severely degrades the practicality of the type.&nbsp; It hurts us deeply to take CLL&lt;T&gt; out but its performance just wasn\u2019t good enough to ship it.&nbsp; No need to send any flowers.<\/P>\n<P><STRONG>Lazy&lt;T&gt;, LazyInitializer, and ThreadLocal&lt;T&gt; <BR><\/STRONG>Oh boy has Lazy&lt;T&gt; been fun!&nbsp; In Beta 1, we told you that we renamed LazyInit&lt;T&gt; to Lazy&lt;T&gt;, added a new struct-based version called LazyVariable&lt;T&gt; and moved the thread-local mode over to its own type (ThreadLocal&lt;T&gt;).&nbsp; Well, in the interest of making these primitives as usable as possible, we\u2019ve gone and done it again!&nbsp; Here\u2019s a breakdown of the lazy-initialization primitives in Beta 2:<\/P>\n<UL>\n<LI>Lazy&lt;T&gt; is still a class-based lazy initialization primitive that\u2019s safe to pass around.&nbsp; We\u2019ve given it it a simple constructor that accepts a bool to indicate whether it needs to be thread-safe or not.*&nbsp; <BR><BR>Also, we now detect recursive calls to Value in the valueFactory delegate.&nbsp; If your valueFactory delegate attempts to access the Value property on the Lazy&lt;T&gt; to which it was passed, an InvalidOperationException will be thrown.&nbsp; <BR><BR>Furthermore, we firmed up our stance on exception handling.&nbsp; In the interest of keeping the type observationally pure, if a valueFactory delegate throws an exception, that exception will be cached and subsequent calls to Value will result in that same exception being rethrown.&nbsp; <BR><\/LI>\n<LI>LazyExecutionMode has been removed now that we have only two simple initialization modes on Lazy&lt;T&gt;* <BR><\/LI>\n<LI>LazyVariable&lt;T&gt; has also been removed (<A href=\"https:\/\/blogs.msdn.com\/pfxteam\/archive\/2009\/05\/26\/9641683.aspx\" target=\"_blank\">we said it would!<\/A>).&nbsp; There were just too many issues with having a struct-based version.&nbsp; If you need lighter-weight lazy initialization, use LazyInitializer.&nbsp; If you need the lighter-weight and an object to pass around, it\u2019s simple enough to create your own struct that uses LazyInitializer\u2019s methods internally.&nbsp; <BR><\/LI>\n<LI>LazyInitializer still contains all the advanced static methods for lazy initialization patterns. <BR><\/LI>\n<LI>ThreadLocal&lt;T&gt; remains unchanged other than some great perf improvements! <\/LI><\/UL>\n<P>*Though in Beta 2 we reduced the number of execution modes to simply thread-safe and not-thread-safe, customer requests have proven that we still need the three.&nbsp; By RTM, there will be an additive constructor to support advanced developers that need tighter control over how thread-safety is achieved.&nbsp; Mostly, this is to enable library writers to use third-party initialization delegates without having to worry if they take locks and will potentially cause a deadlock.&nbsp; Regardless, feel free to use the constructors provided today as any changes are purely additive.<\/P>\n<P><STRONG>Serialization <BR><\/STRONG>In Beta 1, ConcurrentBag&lt;T&gt;, ConcurrentDictionary&lt;TKey,TValue&gt;, ConcurrentQueue&lt;T&gt;, ConcurrentStack&lt;T&gt;, and Lazy&lt;T&gt; all implemented ISerializable.&nbsp; Turns out we were a little behind the times.&nbsp; ISerializable is not version tolerant. We\u2019ve remedied the situation and all of these types now use <A href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms229752(VS.80).aspx\" target=\"_blank\">VTS<\/A> for serialization, with little to no impact on you!<\/P>\n<P>Have fun with Beta 2 and drop us a line. We\u2019d love any feedback you have on the changes!<\/P>\n<P>Josh and the coordination data structures crew<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Rejoice!&nbsp; Visual Studio 2010 Beta 2 is upon us and it includes lots of great changes for the Parallel Extensions.&nbsp; TPL guru Danny Shih has already covered what\u2019s new in TPL and PLINQ aficionado Ed Essey has covered the best way to use LINQ (specifically between Beta 1 and Beta 2) but your favorite set [&hellip;]<\/p>\n","protected":false},"author":486,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7908],"tags":[],"class_list":["post-55961","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam"],"acf":[],"blog_post_summary":"<p>Rejoice!&nbsp; Visual Studio 2010 Beta 2 is upon us and it includes lots of great changes for the Parallel Extensions.&nbsp; TPL guru Danny Shih has already covered what\u2019s new in TPL and PLINQ aficionado Ed Essey has covered the best way to use LINQ (specifically between Beta 1 and Beta 2) but your favorite set [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/55961","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/486"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=55961"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/55961\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=55961"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=55961"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=55961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}