<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devplanet.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>What are we going to do tomorrow night, Brain?  : IDisposable, Threading</title><link>http://devplanet.com/blogs/brianr/archive/tags/IDisposable/Threading/default.aspx</link><description>Tags: IDisposable, Threading</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 (Build: 30912.2823)</generator><item><title>Thread Safe Library Update</title><link>http://devplanet.com/blogs/brianr/archive/2009/09/02/thread-safe-library-update.aspx</link><pubDate>Wed, 02 Sep 2009 16:33:00 GMT</pubDate><guid isPermaLink="false">6e120f4b-f509-4111-8fd8-03bc0d0a75d9:15986</guid><dc:creator>Brian Rudolph</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devplanet.com/blogs/brianr/rsscomments.aspx?PostID=15986</wfw:commentRss><comments>http://devplanet.com/blogs/brianr/archive/2009/09/02/thread-safe-library-update.aspx#comments</comments><description>&lt;p&gt;As always, my life revolves around threading.&amp;nbsp; So&amp;nbsp;I have a few classes that I use frequently for these purposes.&amp;nbsp; Now, fortunately, .NET 4.0 will include much of this functionality in PFX, but for now, we have this.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devplanet.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brianr/ThreadSafe.zip"&gt;ThreadSafeLibrary&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AutoProcessingQueue&lt;/strong&gt;: This is a queue that as you add things to it, will automatically begin dispatching on a seperate thread and begin calling a specified delegate to process the items.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Batch&lt;/strong&gt;: This is a class that is similar to a queue except that it allows you to do work in batches.&amp;nbsp; Set the max &amp;amp; minimum sizes, and start adding items to it.&amp;nbsp; When it reaches a certain size it will attempt to close the batch and will fire an event that will allow you to wire in code for processing the data in the batch.&amp;nbsp; It also has a timer that can be enabled if you&amp;#39;d prefer to allow the batch to be closed at a certain interval.&amp;nbsp; This is great for database calls and bulk inserts.&amp;nbsp; Say I want to send a series of messages, but i don&amp;#39;t want to send them one at a time.&amp;nbsp; I would like to send the messages when the batch reaches 100 items, or every 5 seconds.&amp;nbsp; I use this class alot for messaging.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dispatcher&lt;/strong&gt;:&amp;nbsp; This is the class that does the heavy lifting for the majority of things in this library.&amp;nbsp; You give it a maximum number of threads to work with, and as you add workers to it&amp;#39;s queue, it will begin spawning threads to process them(carefully re-using them whenever possible)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ResourcePool&lt;/strong&gt;:&amp;nbsp; The dispatcher uses this internally to store &amp;amp; manage it&amp;#39;s threads.&amp;nbsp; Though it can be used for any object type.&amp;nbsp; One case where i use this frequently is to pool connections to webservices.&amp;nbsp; To save the time required to open and close connections constantly, i set up a pool, give it a threshold(so as to not flood the service i&amp;#39;m calling) and ask it to get the resource for you via the delegate you provide.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ThreadSafeDictionary&amp;lt;K,V&amp;gt;&lt;/strong&gt;:&amp;nbsp; The classic threadsafe implementation of a dictionary, with several added methods to support atomic operations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ThreadSafeQueue&amp;lt;T&amp;gt;&lt;/strong&gt;:&amp;nbsp; The classic Queue implementation of a dictionary, with several added methods to support atomic operations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ThreadSafeHashSet&amp;lt;T&amp;gt;&lt;/strong&gt;:&amp;nbsp; The classic HashSet implementation of a dictionary, with several added methods to support atomic operations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ThreadSafeStackList&amp;lt;T&amp;gt;&lt;/strong&gt;:&amp;nbsp; This is similar to a stack, without alot of the limitations.&amp;nbsp; Multi-level peek, unwind, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AsyncBlock&lt;/strong&gt;:&lt;br /&gt;This is a class that allows you to wrap async work into serial action for the purposes of simplicity.&amp;nbsp; If you need have a function that needs to run numerous asynchronous calls, and then return only when they are all finished, this is your class.&lt;/p&gt;
&lt;p&gt;You can use it like so:&lt;/p&gt;
&lt;p&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
&lt;tr style="vertical-align:top;line-height:normal;"&gt;&lt;td&gt;&lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;     &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;class&lt;/span&gt; AsyncSample
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; Dispatcher Dispatcher;


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; AsyncSample()
        {
            &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;//init a dispatcher that uses 5 threads and doesn&amp;#39;t carry execution context&lt;/span&gt;
            Dispatcher &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; Dispatcher(5, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;false&lt;/span&gt;);
        }


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; ExecuteParallel&amp;lt;T&amp;gt;(IList&amp;lt;T&amp;gt; work)
        {
            var workers &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; ConstructParallelWorkers(work);


            &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;//the async block will pause this thread until all workers finish&lt;/span&gt;
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (AsyncBlock block &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; AsyncBlock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.Dispatcher, 10))
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;foreach&lt;/span&gt; (var worker &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;in&lt;/span&gt; workers)
                {
                    block.AddToQueue(worker);
                }
            }
        }


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; IList&amp;lt;AnyWorkerBee&amp;lt;T&amp;gt;&amp;gt; ConstructParallelWorkers&amp;lt;T&amp;gt;(IList&amp;lt;T&amp;gt; work)
        {
            var workers &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; List&amp;lt;AnyWorkerBee&amp;lt;T&amp;gt;&amp;gt;();


            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;foreach&lt;/span&gt; (var workUnit &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;in&lt;/span&gt; work)
                workers.Add(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; AnyWorkerBee&amp;lt;T&amp;gt;() { WorkUnit &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; workUnit });


            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; workers;
        }
    }&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=15986" width="1" height="1"&gt;</description><category domain="http://devplanet.com/blogs/brianr/archive/tags/Threading/default.aspx">Threading</category><category domain="http://devplanet.com/blogs/brianr/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devplanet.com/blogs/brianr/archive/tags/Async/default.aspx">Async</category><category domain="http://devplanet.com/blogs/brianr/archive/tags/IDisposable/default.aspx">IDisposable</category></item><item><title>Inline Asynchronous UI Coding using IDisposable in C# .NET</title><link>http://devplanet.com/blogs/brianr/archive/2008/12/15/async-coding-using-idisposable.aspx</link><pubDate>Mon, 15 Dec 2008 17:00:00 GMT</pubDate><guid isPermaLink="false">6e120f4b-f509-4111-8fd8-03bc0d0a75d9:14089</guid><dc:creator>Brian Rudolph</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devplanet.com/blogs/brianr/rsscomments.aspx?PostID=14089</wfw:commentRss><comments>http://devplanet.com/blogs/brianr/archive/2008/12/15/async-coding-using-idisposable.aspx#comments</comments><description>&lt;p&gt;I recently watched this video on the PowerThreading library: &lt;a href="http://blogs.msdn.com/charlie/archive/2008/12/03/jeff-richter-video-on-asynchronous-programming-and-his-power-threading-library.aspx"&gt;http://blogs.msdn.com/charlie/archive/2008/12/03/jeff-richter-video-on-asynchronous-programming-and-his-power-threading-library.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is very interesting as Jeff Richter utilizes a strange behavior in the way the C# compiler works with IEnumerables to make a useful and easy-to-use async library.&amp;nbsp; His primary goal was to allow a website\service yield processing during I/O operations, which can provide for better scalability in your app tier.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;While this is quite interesting, I personally would avoid using strange compilation patterns to my advantage in an application.&amp;nbsp; Specifically because you have no assurance that the compiler will always do this as the language and subsequent compilers evolve.&amp;nbsp; What I was interested in was the mechanism for including asynchronous calls into code without using a complex series of callbacks.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Now, to be quite fair, Jeff&amp;#39;s implementation was an attempt to limit thread spawning, and context switches.&amp;nbsp; I am not going to account for this.&amp;nbsp; I am more interested in parrallel processing.&lt;/p&gt;
&lt;p&gt;Let me give you an example.&amp;nbsp; Take for instance a series of objects that the UI is going to take cues from and make subsequent database calls to retrieve extra data for.&amp;nbsp; A simple example is a treeview.&amp;nbsp; If I have a bunch of nodes in a tree and the UI requires that I display the child node or&amp;nbsp;items&amp;nbsp;count for each of these nodes. What you would generally do is loop through the objects and call the DB to retrieve the data,&amp;nbsp;and assign the UI components in one serial block of code.&amp;nbsp; The problem with this is that the database is more than likely capable of servicing the request for numerous nodes simultaneously, but in the UI we are implementing this serially.&amp;nbsp; If the tree structure is complex, and you are showing more than just a node count, it is plausible that each of these requests will take upward of 50ms.&amp;nbsp; If you have several dozen nodes being displayed this can easily add seconds to your response time.&lt;/p&gt;
&lt;p&gt;A serial block of code might look like this:&lt;/p&gt;
&lt;p&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
&lt;tr style="vertical-align:top;line-height:normal;"&gt;&lt;td&gt;&lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;TreeNodeCollection nodes &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; TreeNodeCollection();
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;foreach&lt;/span&gt; (TreeNode node &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;in&lt;/span&gt; nodes)
{
     &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; objectCount &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; database.DoSomething((MyObject)node.Tag); &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;//call the database&lt;/span&gt;
     node.Text &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; String.Format(&lt;span style="color:#666666;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;quot;{0} ({1})&amp;quot;&lt;/span&gt;, node.Text, objectCount); &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;//update the UI&lt;/span&gt;
 }&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Simple and clean, but slow.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Why not do all of these calls asynchronously, wait for all of the results to filter in, and then update the UI?&amp;nbsp; This should surely be faster than a serial operation.&amp;nbsp; Let&amp;#39;s say, we spawn&amp;nbsp;Math.Min(nodes.Count, 10)&amp;nbsp;threads to accomplish this&amp;nbsp;task.&amp;nbsp; So at a maximum, we will use 10 threads to do the work. If we have 20 nodes, it should take at the longest 2 times as long as the longest running call.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The usual issue with this is that it requires you to use several call-back methods, do complicated thread monitoring, and subsequently put the UI into a wait state until all of the external threads have finished.&amp;nbsp; Unfortunately there just is no simple way to do it.&lt;/p&gt;
&lt;p&gt;So I got to thinking, what construct can I use to signal an asynchronous block, that would prevent execution beyond it&amp;#39;s bounds until all the threads were done.&amp;nbsp; The answer, IDisposable.&amp;nbsp; If I created an IDisposable object and wrapped it in a &amp;quot;using&amp;quot; I could prevent the Dispose method from exiting until all the threads have finished.&lt;/p&gt;
&lt;p&gt;Utilizing the rest of my Threading objects, this should be fairly simple to accomplish, all I had to do was add a done flag to my workerbee:&lt;/p&gt;
&lt;p&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
&lt;tr style="vertical-align:top;line-height:normal;"&gt;&lt;td&gt;&lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;class&lt;/span&gt; AsyncBlock : IDisposable
{


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;long&lt;/span&gt; timeoutMS &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; 0;
        Dispatcher dispatcher &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;null&lt;/span&gt;;
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; started &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;false&lt;/span&gt;;

        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; AsyncBlock() : &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;(10) { }

        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; AsyncBlock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; timeoutSeconds) : &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;(timeoutSeconds, 5) { }

        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; AsyncBlock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; timeoutSeconds, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; threads) : &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; Dispatcher(threads), timeoutSeconds) { }

        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; AsyncBlock(Dispatcher dispatcher, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; timeoutSeconds)
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dispatcher &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; dispatcher;
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.timeoutMS &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; timeoutSeconds &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;*&lt;/span&gt; 1000;
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.WorkQueue &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; List&amp;lt;WorkerBee&amp;gt;();
        }


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; IList&amp;lt;WorkerBee&amp;gt; WorkQueue
        {
            get;
            set;
        } 


       &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; IList&amp;lt;WorkerBee&amp;gt; GetWorkers()        
       {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; List&amp;lt;WorkerBee&amp;gt;(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.WorkQueue);
        } 


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; AddToQueue(WorkerBee bee)
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.WorkQueue.Add(bee);
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dispatcher.AddToQueue(bee);
            started &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;true&lt;/span&gt;;
        }


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Start()
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;foreach&lt;/span&gt; (WorkerBee bee &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;in&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.WorkQueue)
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (!bee.Done)
                    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dispatcher.AddToQueue(bee);


            started &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;true&lt;/span&gt;;
        }


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Dispose()
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (!started &amp;amp;&amp;amp; WorkQueue.Count !&lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; 0)
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;throw&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; Exception(&lt;span style="color:#666666;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;quot;Work was never started&amp;quot;&lt;/span&gt;);
            }


            System.Diagnostics.Stopwatch watch &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; System.Diagnostics.Stopwatch();
            watch.Start();
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; done &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;false&lt;/span&gt;;

            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;while&lt;/span&gt; (!done)
            {
                done &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;true&lt;/span&gt;;
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;foreach&lt;/span&gt; (WorkerBee bee &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;in&lt;/span&gt; WorkQueue)
                {
                    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (!(done &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; done &amp;amp;&amp;amp; bee.Done))
                        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;break&lt;/span&gt;;
                }
 


                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (watch.ElapsedMilliseconds &amp;gt; timeoutMS)
                    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;throw&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; TimeoutException(&lt;span style="color:#666666;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;quot;Timeout elapsed&amp;quot;&lt;/span&gt;);
 
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (!done)
                    Thread.Sleep(1); &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;// wait 1ms to try again&lt;/span&gt;
            }
 
            watch.Stop();
        }
}


&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;class&lt;/span&gt; DatabaseWorkerBee&amp;lt;RefType, ReturnType&amp;gt; : AnyWorkerBee&amp;lt;Delegate&amp;gt;
{
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;delegate&lt;/span&gt; ReturnType DBDelegate();
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;private&lt;/span&gt; DBDelegate dbDelegate;

        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; ReturnType ReturnValue
        {
            get;
            set;
        } 


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; RefType ReferenceObject
        {
            get;
            set;
        } 


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; DatabaseWorkerBee(RefType refObject, DBDelegate del)
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.ReferenceObject &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; refObject;
            dbDelegate &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; del;
        } 


        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; WorkStart()
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;base&lt;/span&gt;.WorkStart();
 
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (dbDelegate !&lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;null&lt;/span&gt;)
            {
                ReturnValue &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; dbDelegate();
            }
        }
    }


 &lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Alright, this is now a fairly simple implementation in&amp;nbsp; the UI:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
&lt;tr style="vertical-align:top;line-height:normal;"&gt;&lt;td&gt;&lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;IList&amp;lt;WorkerBee&amp;gt; workers &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;null&lt;/span&gt;;


&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (AsyncBlock block &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; AsyncBlock(30, Math.Min(nodes.Count, 10))) &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;// do these async with a 30 second timeout&lt;/span&gt;
{
      &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;foreach&lt;/span&gt; (TreeNode o &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;in&lt;/span&gt; nodes)
      {
          TreeNode node &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; o; &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;//must declare this in the loop, or you get the same object in every worker, this is a documented closure bug in the framework&lt;/span&gt;
          block.AddToQueue(
              &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; DatabaseWorkerBee&amp;lt;TreeNode, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt;&amp;gt;( node, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;delegate&lt;/span&gt; { &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/* Do Database Call Here using the node object*/&lt;/span&gt;; }));
       }


      workers &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; block.GetWorkers()


}&lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;//using will not return until all workers have been processed.&lt;/span&gt;


&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;foreach&lt;/span&gt; (WorkerBee worker &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;in&lt;/span&gt; workers)
{
      DatabaseWorkerBee&amp;lt;TreeNode, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt;&amp;gt; dbworker &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; worker &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;as&lt;/span&gt; DatabaseWorkerBee&amp;lt;TreeNode, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt;&amp;gt;;
      dbWorker.ReferenceObject.Text &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; String.Format(&lt;span style="color:#666666;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;quot;{0} ({1})&amp;quot;&lt;/span&gt;, dbWorker.ReferenceObject.Text, dbWorker.ReturnValue); &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;//update the UI&lt;/span&gt;
}


 &lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Woot!&amp;nbsp; All of the nodes are executed async, and all of the values are returned properly.&amp;nbsp; One thing to note, notice I am declaring a redundant TreeNode object inside the loop.&amp;nbsp; This is necessary, since we are using an anonymous method inside of the loop.&amp;nbsp; If we were to just reference the &amp;quot;o&amp;quot; in the iterator, we would get the same object passed to each anonymous method.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;My Threading Objects can be found here: &lt;a href="http://devplanet.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/brianr.Code+Snippets/ThreadingLib.zip"&gt;ThreadLib.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[Edit]&lt;br /&gt;After further review and testing this code works quite well, except in the instance of windows authenticated database connections.&amp;nbsp; Because we are spawning new threads, and your security context is thread based, all of the subsequent database calls were made using the applications default user.&amp;nbsp; This isn&amp;#39;t a problem in Windows UI&amp;#39;s but in Web apps this is not good.&amp;nbsp; It could be as simple as setting the new threads to the same security context as the spawning thread, but I&amp;#39;m not sure I want that to happen for every thread.&amp;nbsp; I will work this out and do an update.&lt;/p&gt;
&lt;p&gt;I have worked this security context issue out. If anyone is interested in it, email me.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=14089" width="1" height="1"&gt;</description><category domain="http://devplanet.com/blogs/brianr/archive/tags/Threading/default.aspx">Threading</category><category domain="http://devplanet.com/blogs/brianr/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devplanet.com/blogs/brianr/archive/tags/Async/default.aspx">Async</category><category domain="http://devplanet.com/blogs/brianr/archive/tags/IDisposable/default.aspx">IDisposable</category></item><item><title>Thread Safe Dictionary in .NET with ReaderWriterLockSlim</title><link>http://devplanet.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx</link><pubDate>Fri, 26 Sep 2008 15:14:00 GMT</pubDate><guid isPermaLink="false">6e120f4b-f509-4111-8fd8-03bc0d0a75d9:13</guid><dc:creator>Brian Rudolph</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devplanet.com/blogs/brianr/rsscomments.aspx?PostID=13</wfw:commentRss><comments>http://devplanet.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx#comments</comments><description>&lt;p&gt;Since&amp;nbsp;MS has decided to not include a thread-safe dictionary in the .NET framework, many of us have been forced to implement our own.&amp;nbsp; What MS has done&amp;nbsp;now with .NET 3.5 is given us a newer locking mechanism which makes this task easier.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Previously, we had 2 lock mechanisms, neither of which worked very well for my uses.&amp;nbsp; The first is the Lock statement.&amp;nbsp; While this method is effective, it causes serious contention issues with simultaneous reads\writes.&amp;nbsp; Since it is generally safe to execute multiple concurrent reads from a dictionary, this was a huge performance flaw as the Lock statement was forcing us to perform all actions against the object in a serial fashion.&lt;/p&gt;
&lt;p&gt;So that left ReaderWriterLock, which would allow us to take out Reader &amp;amp; Writer locks independently.&amp;nbsp; This seemed to be the answer.&amp;nbsp; Unfortunately, after further testing and review, MS and the dev communities warned against this lock type&amp;nbsp;as it could have unintended consequences in certain situations.&amp;nbsp; The explanations for these I will not go in to, a simple Google search will answer those questions.&amp;nbsp; For the most part, I don&amp;#39;t have the mental capacity to understand, much less explain the failures.&amp;nbsp; I will tell you that I have tested this method, and ran in to some issues, and subsequently abandoned the approach.&lt;/p&gt;
&lt;p&gt;With&amp;nbsp;.NET 3.5 comes the brand-spankin-new ReaderWriterLockSlim.&amp;nbsp;&amp;nbsp;ReaderWriterLockSlim is similar to the ReaderWriterLock in functionality, minus some of the drawbacks.&amp;nbsp; Of course any new approach will bring on its own consequences, and if you do a little research, you will find that Slim isn&amp;#39;t infallible either.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Many of our applications implement the Factory model.&amp;nbsp; Factory models are great, they are extensible, and they can be extremely performant.&amp;nbsp; With that said, any data driven application that uses the Factory model without a caching model, will most likely perform poorly.&amp;nbsp; So, in our factories, we build in a caching mechanism.&amp;nbsp; A very simple type and ID based cache that allows us to persist commonly used objects to in-memory cache for a specific amount of time.&amp;nbsp; I won&amp;#39;t go in to the implementation of this model here as every caching implementation has its own needs and wants.&lt;/p&gt;
&lt;p&gt;At the heart of this&amp;nbsp;and likely any caching model is inevitably a Dictionary or Dictionary like structure.&amp;nbsp; MS programmers have spent countless hours fine-tuning the Dictionary class to make it as performant as possible.&amp;nbsp; I challenge anyone to write a managed Dictionary that performs as well in such a wide variety of scenarios.&amp;nbsp; I&amp;#39;ve tried and failed.&amp;nbsp; Unfortunately, MS has not provided a thread-safe implementation.&amp;nbsp; Generally when you run into the question of thread-safety, most people have no idea what you are talking about.&amp;nbsp; The problem with writing truly thread-safe code that can work in any scenario is that you will sacrifice performance.&amp;nbsp; If you tailor your thread-safe mechanisms to your particular problem, you can generally maintain a higher level of performance.&lt;/p&gt;
&lt;p&gt;The reason we need thread-safety is not that we are specifically spawning threads.&amp;nbsp; In IIS, worker processes are inherently multi-threaded.&amp;nbsp; Therefore, using static objects in a web-farm generally requires some level of thread safety, otherwise you will get dreaded &amp;quot;An item with the same key has already been added&amp;quot; errors.&amp;nbsp; This is because between the time you check to see if a key already exists in your dictionary and the time you insert it, some other thread may have inserted this key.&amp;nbsp; This is especially the case in object factories, because you have multiple threads attempting to access/create objects and subsequently cache them.&lt;/p&gt;
&lt;p&gt;This is the code I&amp;#39;ve written.&amp;nbsp;&amp;nbsp;Update: This code has been tested, and is working well.&amp;nbsp; I will keep this post updated with any changes and test results.&amp;nbsp; I also have not made this class utilize lock escalation, which ReaderWriterLockSlim supports.&amp;nbsp; As always, &lt;strong&gt;please perform your own testing&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;table cellpadding="0" cellspacing="0" style="background-color:#f2f2f2;border:solid 1px #e5e5e5;width:100%;"&gt;
&lt;tr style="vertical-align:top;line-height:normal;"&gt;&lt;td&gt;&lt;pre style="overflow:scroll;margin:0px;padding:2px;padding-left:8px;"&gt;&lt;span style="color:Black;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; System;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; System.Collections;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; System.Threading;


&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;interface&lt;/span&gt; IThreadSafeDictionary&amp;lt;TKey, TValue&amp;gt; : IDictionary&amp;lt;TKey, TValue&amp;gt;
{
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// Merge is similar to the SQL merge or upsert statement.  &lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;param name=&amp;quot;key&amp;quot;&amp;gt;Key to lookup&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;param name=&amp;quot;newValue&amp;quot;&amp;gt;New Value&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; MergeSafe(TKey key, TValue newValue);


    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// This is a blind remove. Prevents the need to check for existence first.&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;param name=&amp;quot;key&amp;quot;&amp;gt;Key to Remove&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; RemoveSafe(TKey key);
}


[Serializable]
&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;class&lt;/span&gt; ThreadSafeDictionary&amp;lt;TKey, TValue&amp;gt; : IThreadSafeDictionary&amp;lt;TKey, TValue&amp;gt;
{
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;//This is the internal dictionary that we are wrapping&lt;/span&gt;
    IDictionary&amp;lt;TKey, TValue&amp;gt; dict &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; Dictionary&amp;lt;TKey, TValue&amp;gt;();


    [NonSerialized]
    ReaderWriterLockSlim dictionaryLock &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; Locks.GetLockInstance(LockRecursionPolicy.NoRecursion); &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;//setup the lock;&lt;/span&gt;


    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// This is a blind remove. Prevents the need to check for existence first.&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;param name=&amp;quot;key&amp;quot;&amp;gt;Key to remove&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; RemoveSafe(TKey key)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.ContainsKey(key))
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; WriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
                {
                    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Remove(key);
                }
            }
        }
    }


    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// Merge does a blind remove, and then add.  Basically a blind Upsert.  &lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;param name=&amp;quot;key&amp;quot;&amp;gt;Key to lookup&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;/// &amp;lt;param name=&amp;quot;newValue&amp;quot;&amp;gt;New Value&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; MergeSafe(TKey key, TValue newValue)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; WriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock)) &lt;span style="color:Green;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;// take a writelock immediately since we will always be writing&lt;/span&gt;
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.ContainsKey(key))
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Remove(key);
            }


            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Add(key, newValue);
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; Remove(TKey key)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; WriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Remove(key);
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; ContainsKey(TKey key)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.ContainsKey(key);
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; TryGetValue(TKey key, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;out&lt;/span&gt; TValue value)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.TryGetValue(key, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;out&lt;/span&gt; value);
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; TValue &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;[TKey key]
    {
        get
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict[key];
            }
        }
        set
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; WriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict[key] &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; value;
            }
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; ICollection&amp;lt;TKey&amp;gt; Keys
    {
        get
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; List&amp;lt;TKey&amp;gt;(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Keys);
            }
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; ICollection&amp;lt;TValue&amp;gt; Values
    {
        get
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; List&amp;lt;TValue&amp;gt;(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Values);
            }
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Clear()
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; WriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Clear();
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; Count
    {
        get
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Count;
            }
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; Contains(KeyValuePair&amp;lt;TKey, TValue&amp;gt; item)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Contains(item);
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Add(KeyValuePair&amp;lt;TKey, TValue&amp;gt; item)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; WriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Add(item);
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Add(TKey key, TValue value)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; WriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Add(key, value);
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; Remove(KeyValuePair&amp;lt;TKey, TValue&amp;gt; item)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; WriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.Remove(item);
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; CopyTo(KeyValuePair&amp;lt;TKey, TValue&amp;gt;[] array, &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;int&lt;/span&gt; arrayIndex)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.CopyTo(array, arrayIndex);
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; IsReadOnly
    {
        get
        {
            &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;using&lt;/span&gt; (&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dictionaryLock))
            {
                &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;.dict.IsReadOnly;
            }
        }
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;virtual&lt;/span&gt; IEnumerator&amp;lt;KeyValuePair&amp;lt;TKey, TValue&amp;gt;&amp;gt; GetEnumerator()
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;throw&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; NotSupportedException(&lt;span style="color:#666666;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;quot;Cannot enumerate a threadsafe dictionary.  Instead, enumerate the keys or values collection&amp;quot;&lt;/span&gt;);
    }


    IEnumerator IEnumerable.GetEnumerator()
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;throw&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; NotSupportedException(&lt;span style="color:#666666;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;&amp;quot;Cannot enumerate a threadsafe dictionary.  Instead, enumerate the keys or values collection&amp;quot;&lt;/span&gt;);
    }
}


&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;class&lt;/span&gt; Locks
{
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; GetReadLock(ReaderWriterLockSlim locks)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; lockAcquired &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;false&lt;/span&gt;;
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;while&lt;/span&gt; (!lockAcquired)
            lockAcquired &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; locks.TryEnterUpgradeableReadLock(1);
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; GetReadOnlyLock(ReaderWriterLockSlim locks)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; lockAcquired &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;false&lt;/span&gt;;
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;while&lt;/span&gt; (!lockAcquired)
            lockAcquired &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; locks.TryEnterReadLock(1);
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; GetWriteLock(ReaderWriterLockSlim locks)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;bool&lt;/span&gt; lockAcquired &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;false&lt;/span&gt;;
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;while&lt;/span&gt; (!lockAcquired)
            lockAcquired &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; locks.TryEnterWriteLock(1);
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; ReleaseReadOnlyLock(ReaderWriterLockSlim locks)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (locks.IsReadLockHeld)
            locks.ExitReadLock();
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; ReleaseReadLock(ReaderWriterLockSlim locks)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (locks.IsUpgradeableReadLockHeld)
            locks.ExitUpgradeableReadLock();
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; ReleaseWriteLock(ReaderWriterLockSlim locks)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;if&lt;/span&gt; (locks.IsWriteLockHeld)
            locks.ExitWriteLock();
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; ReleaseLock(ReaderWriterLockSlim locks)
    {
        ReleaseWriteLock(locks);
        ReleaseReadLock(locks);
        ReleaseReadOnlyLock(locks);
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; ReaderWriterLockSlim GetLockInstance()
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; GetLockInstance(LockRecursionPolicy.SupportsRecursion);
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;static&lt;/span&gt; ReaderWriterLockSlim GetLockInstance(LockRecursionPolicy recursionPolicy)
    {
        &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;new&lt;/span&gt; ReaderWriterLockSlim(recursionPolicy);
    }
}


&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;abstract&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;class&lt;/span&gt; BaseLock : IDisposable
{
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;protected&lt;/span&gt; ReaderWriterLockSlim _Locks;


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; BaseLock(ReaderWriterLockSlim locks)
    {
        _Locks &lt;span style="color:Red;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;=&lt;/span&gt; locks;
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;abstract&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Dispose();
}


&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;class&lt;/span&gt; ReadLock : BaseLock
{
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; ReadLock(ReaderWriterLockSlim locks)
        : &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;base&lt;/span&gt;(locks)
    {
        Locks.GetReadLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;._Locks);
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Dispose()
    {
        Locks.ReleaseReadLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;._Locks);
    }
}


&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;class&lt;/span&gt; ReadOnlyLock : BaseLock
{
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; ReadOnlyLock(ReaderWriterLockSlim locks)
        : &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;base&lt;/span&gt;(locks)
    {
        Locks.GetReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;._Locks);
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Dispose()
    {
        Locks.ReleaseReadOnlyLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;._Locks);
    }
}


&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;class&lt;/span&gt; WriteLock : BaseLock
{
    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; WriteLock(ReaderWriterLockSlim locks)
        : &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;base&lt;/span&gt;(locks)
    {
        Locks.GetWriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;._Locks);
    }


    &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;void&lt;/span&gt; Dispose()
    {
        Locks.ReleaseWriteLock(&lt;span style="color:Blue;background-color:Transparent;font-family:Courier New;font-size:11px;font-weight:normal;"&gt;this&lt;/span&gt;._Locks);
    }
}


 &lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;[Update]&lt;br /&gt;Through some testing, I found the need to update the ThreadSafe Dictionary.&amp;nbsp; I changed all of the locking to use IDisposables to ensure lock creation and destruction.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devplanet.com/aggbug.aspx?PostID=13" width="1" height="1"&gt;</description><category domain="http://devplanet.com/blogs/brianr/archive/tags/Dictionary/default.aspx">Dictionary</category><category domain="http://devplanet.com/blogs/brianr/archive/tags/Threading/default.aspx">Threading</category><category domain="http://devplanet.com/blogs/brianr/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devplanet.com/blogs/brianr/archive/tags/IDisposable/default.aspx">IDisposable</category></item></channel></rss>