<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-30604582</id><updated>2012-01-23T16:42:37.149Z</updated><title type='text'>.NET Mutterings</title><subtitle type='html'>Andy's observations as he continues to attempt to know all that is .NET...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default?start-index=101&amp;max-results=100'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>104</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-30604582.post-8619815669824256673</id><published>2012-01-17T21:24:00.001Z</published><updated>2012-01-17T21:24:27.309Z</updated><title type='text'>Developmentor has moved</title><content type='html'>&lt;p&gt;&lt;b&gt;In addition to working hard at RSK myself and Richard are also instructors for Developmtor.&amp;#160; Both of us author and teach a range of courses for them.&amp;#160; This year has seen Developmentor move from Hammersmith to central London, for all of you who are based in and around London they are offering an evening of tech and nibbles to show case the new location.&amp;#160; Details below, hopefully see some of you there. &lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Come and see us! On Monday 6th February 2012, 5-7pm &lt;/b&gt;to cement the move to our new London City location in Moorgate, we invite you to our house warming, entertainment provided by &lt;a href="http://www.develop.com/technicalstaff#Richard Blewett"&gt;Richard Blewett&lt;/a&gt; and &lt;a href="http://www.develop.com/technicalstaff#Andrew Clymer"&gt;Andy Clymer&lt;/a&gt;who will be revealing the magic behind the new and exciting C#5 Async and AWait keywords. To register your interest for this free event, please email us &lt;a href="mailto:salesuk@develop.com"&gt;salesuk@develop.com &lt;/a&gt;or call 01242 525108 .&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8619815669824256673?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8619815669824256673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8619815669824256673' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8619815669824256673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8619815669824256673'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2012/01/developmentor-has-moved.html' title='Developmentor has moved'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-4677896670895261384</id><published>2012-01-12T22:47:00.001Z</published><updated>2012-01-12T22:47:55.968Z</updated><title type='text'>Code smarter with Design Patterns</title><content type='html'>&lt;p&gt;Just finished updating the Code Smarter with Design Patterns for &lt;a href="http://www.develop.com"&gt;Developmentor&lt;/a&gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;The course traditionally has focused on GoF design patterns, in this release I have added MVC and Repository pattern, to round off the offering.&lt;/p&gt;  &lt;p&gt;Both these patterns build upon the GoF patterns discussed earlier in the course, and show how the basic GoF patterns are often compounded to produce elegant solutions.&lt;/p&gt;  &lt;p&gt;Other enhancements include addition of Prototype and Builder patterns, and a general upgrade to the latest features offered by the .NET framework.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;To learn more click &lt;a href="http://www.develop.com/training-course/net-design-patterns"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-4677896670895261384?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/4677896670895261384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=4677896670895261384' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4677896670895261384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4677896670895261384'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2012/01/code-smarter-with-design-patterns.html' title='Code smarter with Design Patterns'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6712137806207404786</id><published>2011-11-24T10:01:00.001Z</published><updated>2011-11-24T10:01:28.331Z</updated><title type='text'>Devweek 2012</title><content type='html'>&lt;p&gt;RSK guys will be speaking at &lt;a href="http://www.devweek.com/"&gt;DevWeek&lt;/a&gt; this year, and as usual we will be talking about a large range of cutting edge topics, including&lt;/p&gt;  &lt;p&gt;Our fluffy cuddly colouring in guy Dave Wheeler will be doing a huge number of sessions on Windows 8 Metro including the Keynote to get you all fired up, but don’t think they will be all soft, one session includes a COM primer for all those youngsters who didn’t take their COM apprentiship.&lt;/p&gt;  &lt;p&gt;Rich will be covering topics from Whats New in WCF 4.5, and the ever cool Reactive Framework, and a deep dive into the GC, something all developers should have intimate knowledge of.&lt;/p&gt;  &lt;p&gt;Andy will be covering the new async functionality of C#5, highlighting how you now write both ui and server side code to consume and enable the use of these new wonderful keywords, and doing a whole day of threading as a pre con on Monday&lt;/p&gt;  &lt;p&gt;Kevin will be presenting a day of building MVC applications, along with a session on unit testing.&amp;#160; &lt;/p&gt;  &lt;p&gt;During the breaks Dr Rock Man will also be there to try and solve your specific technical problems or just happy to hear you rant about the code base you have just inherited. &lt;/p&gt;  &lt;p&gt;In total we will be presenting a total 19 sessions, plus pre and post conference sessions.&amp;#160; Hopefully see you &lt;a href="http://www.devweek.com/"&gt;there&lt;/a&gt; with what should be a fun pact week..&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6712137806207404786?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6712137806207404786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6712137806207404786' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6712137806207404786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6712137806207404786'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/11/devweek-2012.html' title='Devweek 2012'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8177027063012623816</id><published>2011-08-12T14:44:00.001+01:00</published><updated>2011-08-12T14:44:39.754+01:00</updated><title type='text'>Customer Access Terminal V2</title><content type='html'>&lt;p&gt;Rich and myself are just about to install the next version of our Customer Access Terminal solution at one of our existing customers.&amp;#160; So it seems a convenient time to mention we now have a web site that provides a detailed overview of all the features in V2.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.face2faceAssist.com"&gt;Face 2 Face Asssit&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8177027063012623816?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8177027063012623816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8177027063012623816' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8177027063012623816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8177027063012623816'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/08/customer-access-terminal-v2.html' title='Customer Access Terminal V2'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-1939546588617569200</id><published>2011-03-31T16:10:00.001+01:00</published><updated>2011-03-31T16:10:48.978+01:00</updated><title type='text'>CAT Terminal on film</title><content type='html'>&lt;p&gt;The council that recently purchased our CAT kiosk made a short movie for their local tv station, if you are interested in seeing the CAT in action&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.cheshirewest.tv/categories/my-services/film/newsdesk-march-2011/"&gt;Click here&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The CAT piece is 1 minute 29 seconds into the movie.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-1939546588617569200?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/1939546588617569200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=1939546588617569200' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1939546588617569200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1939546588617569200'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/03/cat-terminal-on-film.html' title='CAT Terminal on film'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-1282591364438059092</id><published>2011-03-22T16:59:00.001Z</published><updated>2011-03-22T16:59:43.810Z</updated><title type='text'>CAT Terminal</title><content type='html'>&lt;p&gt;Following up from my recent post on our CAT kiosk deployment.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.chesterfirst.co.uk/news/100188/new-videolink-for-tarporley-library.aspx" target="_blank"&gt;Here is a link to the councils own article&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-1282591364438059092?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/1282591364438059092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=1282591364438059092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1282591364438059092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1282591364438059092'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/03/cat-terminal.html' title='CAT Terminal'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-5647507558645289713</id><published>2011-03-12T14:07:00.001Z</published><updated>2011-03-12T14:07:53.193Z</updated><title type='text'>Customer Access Terminal (CAT)</title><content type='html'>&lt;p&gt;Yesterday was a big day for Rich and myself we successfully deployed our CAT software to our first customer in conjunction with our video conferencing partner First Connections.&amp;#160; The software allows members of the public to interact with their local council almost as if they are with them in person.&amp;#160; Allowing members of the public to access services from rural locations.&lt;/p&gt;  &lt;p&gt;The kiosk utilises two screens, one being a touch screen.&amp;#160; The touch screen is used to visit specific council web sites, or to start a video call with a member from one of the council help desk team.&amp;#160; Once in a video call the council representative can help complete specific council forms including taking passport style photos with the built in HD camera and customers signatures using a high resolution LCD signature pad.&lt;/p&gt;  &lt;p&gt;All built using .NET 4 and Windows Embedded.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OxnULoaN7CE/TXt-LqvQv3I/AAAAAAAAA1c/LETbvdPCvU4/s1600-h/IMG_1322%5B2%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="IMG_1322" border="0" alt="IMG_1322" src="http://lh6.ggpht.com/_OxnULoaN7CE/TXt-L1EDOoI/AAAAAAAAA1g/fwPP_0pp-7M/IMG_1322_thumb.jpg?imgmax=800" width="244" height="183" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_OxnULoaN7CE/TXt-MwWI9vI/AAAAAAAAA1k/FaVCvGoP274/s1600-h/IMG_1327%5B2%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="IMG_1327" border="0" alt="IMG_1327" src="http://lh3.ggpht.com/_OxnULoaN7CE/TXt-NUUKQJI/AAAAAAAAA1o/mfvOCtMSrHs/IMG_1327_thumb.jpg?imgmax=800" width="244" height="183" /&gt;&lt;/a&gt; &lt;a href="http://lh6.ggpht.com/_OxnULoaN7CE/TXt-NsVs4oI/AAAAAAAAA1s/eYq8sZgQcoo/s1600-h/IMG_1325%5B2%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="IMG_1325" border="0" alt="IMG_1325" src="http://lh4.ggpht.com/_OxnULoaN7CE/TXt-OH8UciI/AAAAAAAAA1w/HbwFWpIqZTY/IMG_1325_thumb.jpg?imgmax=800" width="244" height="183" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-5647507558645289713?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/5647507558645289713/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=5647507558645289713' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5647507558645289713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5647507558645289713'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/03/customer-access-terminal-cat.html' title='Customer Access Terminal (CAT)'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_OxnULoaN7CE/TXt-L1EDOoI/AAAAAAAAA1g/fwPP_0pp-7M/s72-c/IMG_1322_thumb.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8917742020928807291</id><published>2011-03-10T16:26:00.001Z</published><updated>2011-03-10T16:26:25.040Z</updated><title type='text'>Concurrent Data Structures screen cast</title><content type='html'>&lt;p&gt;Must be screen cast Thursday, another screen cast posted to RSK on Concurrent Data Structures in .NET 4&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.rocksolidknowledge.com/screencasts" target="_blank"&gt;RSK screen casts&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8917742020928807291?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8917742020928807291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8917742020928807291' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8917742020928807291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8917742020928807291'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/03/concurrent-data-structures-screen-cast.html' title='Concurrent Data Structures screen cast'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-501220225366007920</id><published>2011-03-10T12:52:00.001Z</published><updated>2011-03-10T12:52:11.182Z</updated><title type='text'>async and await screencast</title><content type='html'>&lt;p&gt;Just uploaded a new screencast on async and await keywords due to be introduced in C# 5.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.rocksolidknowledge.com/screencasts.mvc" target="_blank"&gt;Rock Solid Knowledge Screencasts&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-501220225366007920?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/501220225366007920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=501220225366007920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/501220225366007920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/501220225366007920'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/03/async-and-await-screencast.html' title='async and await screencast'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8253427283517620314</id><published>2011-02-11T06:59:00.001Z</published><updated>2011-02-11T06:59:28.432Z</updated><title type='text'>TPL Dataflow</title><content type='html'>&lt;p&gt;One parallel pattern that required some work with base .NET 4 was parallel pipe lines.&amp;#160; The CTP release of the Parallel Dataflow extensions, makes this trivial now.&amp;#160; I’m intending to do a screencast really soon to show this action, but in the mean time try it out for yourself you can &lt;a href="http://msdn.microsoft.com/en-us/devlabs/gg585582"&gt;download it from here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8253427283517620314?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8253427283517620314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8253427283517620314' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8253427283517620314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8253427283517620314'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/02/tpl-dataflow.html' title='TPL Dataflow'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8816041966901303271</id><published>2011-02-09T11:35:00.001Z</published><updated>2011-02-09T11:35:45.300Z</updated><title type='text'>Coding Challenge,an alternative to regular class room training</title><content type='html'>&lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;p&gt;What do most engineers want to do, “Build Things”. Regular training classes are good at introducing new technology, but what if you want to take it further; to stretch and motivate your senior developers. This was the requirement that our major investment bank client presented to Rock Solid Knowledge the co-developed solution was to produce a Coding Challenge…&lt;/p&gt;  &lt;h4&gt;The Training Day One&lt;/h4&gt;  &lt;p&gt;The first day was spent with a deep dive into Silverlight; all teams had prior knowledge of WPF. The focus of the day was to effectively demonstrate the differences and similarities of the two technologies, giving the teams the ability to deliver a high quality Silverlight solution to match the code challenge requirements document.&lt;/p&gt;  &lt;h4&gt;The Challenge Day Two&lt;/h4&gt;  &lt;p&gt;The three person teams, of senior developers, spent the next 24 hours straight building a working product to the supplied specification. Not only did this test their ability to apply the new technology but demonstrated who ships and who doesn’t. Failing to organise is clearly highlighted when you only have a short period of time to deliver.&lt;/p&gt;  &lt;h4&gt;The Assessment Day Three&lt;/h4&gt;  &lt;p&gt;After working nearly flat out for 24 hours the teams submitted their solutions to be assessed by Rock Solid Knowledge. Initial marks were given, with each team then given a technical grilling on their solution to provide feedback on what was good and bad.&lt;/p&gt;  &lt;h4&gt;The Winner&lt;/h4&gt;  &lt;p&gt;The winning team all received iPads, a satisfactory reward for all their hard efforts and our client introduced a new technology in a vibrant and compelling way.&lt;/p&gt;  &lt;p&gt;If this has wetted your appetite a more detailed write up can be downloaded from &lt;a href="http://rocksolidknowledge.blob.core.windows.net/downloads/Full+Coding+Challenge.pdf"&gt;here&lt;/a&gt; or if you would just simply like to know how we could bring this experience to your company contact us by clicking &lt;a href="http://www.rocksolidknowledge.com/ContactUs.mvc/"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8816041966901303271?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8816041966901303271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8816041966901303271' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8816041966901303271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8816041966901303271'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/02/coding-challengean-alternative-to.html' title='Coding Challenge,an alternative to regular class room training'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-744306029416948424</id><published>2011-02-03T08:22:00.001Z</published><updated>2011-02-03T08:22:26.687Z</updated><title type='text'>No more free Reflector</title><content type='html'>&lt;p&gt;Red Gate have announced that from the next release in March no more free versions of Reflector.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.red-gate.com/products/dotnet-development/reflector/announcement"&gt;http://www.red-gate.com/products/dotnet-development/reflector/announcement&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-744306029416948424?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/744306029416948424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=744306029416948424' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/744306029416948424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/744306029416948424'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/02/no-more-free-reflector.html' title='No more free Reflector'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-5977291092075806086</id><published>2011-01-24T09:59:00.001Z</published><updated>2011-01-24T09:59:56.458Z</updated><title type='text'>Devweek 2011</title><content type='html'>&lt;p&gt;Just in case you are not aware &lt;a href="http://www.devweek.com" target="_blank"&gt;Dev Week 2011&lt;/a&gt; is fast approaching, this is without doubt the best independent .NET technical&amp;#160; conference in the UK.&amp;#160; I’m delighted to say that Rock Solid Knowledge will be attending again this year delivering a variety of sessions from Parallel programming to Workflow to fluffy UI.&amp;#160; A full list of our sessions can be found &lt;a href="http://www.rocksolidknowledge.com/conferences.mvc" target="_blank"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img alt="image" src="http://lh6.ggpht.com/_OxnULoaN7CE/S2qq5oV1XfI/AAAAAAAAAqY/9m97LN_2DU0/image_thumb.png?imgmax=800" /&gt;&lt;/p&gt;  &lt;p&gt;In addition to the traditional lecture sessions we will be running our drop in clinic where our consultants will help you solve your design and development issues.&amp;#160; The whole team will be there so whether its WPF, Silverlight, .NET 4.0, WCF , Design Patterns, Multithreading, Web Development or anything else, we’ll be on hand to lend a sympathetic ear and hopefully solve your problems. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-5977291092075806086?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/5977291092075806086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=5977291092075806086' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5977291092075806086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5977291092075806086'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2011/01/devweek-2011.html' title='Devweek 2011'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_OxnULoaN7CE/S2qq5oV1XfI/AAAAAAAAAqY/9m97LN_2DU0/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8646374059620055218</id><published>2010-06-04T12:53:00.001+01:00</published><updated>2010-06-04T12:54:02.237+01:00</updated><title type='text'>Software Architecture 2010</title><content type='html'>&lt;p&gt;Myself and other Rock Solid Knowledge guys have had various talks accepted for Software Architecture conference this October in London.&lt;/p&gt;  &lt;p&gt;Rich and myself will be spending a day talking about how to use various bits of .NET 4 technology to build a MVC, WF and&amp;#160; Entity Framework based application.&amp;#160; The aim to build the app live, so you really get to see how this tech actually ticks.&lt;/p&gt;  &lt;p&gt;Through out the week I’ll be doing stuff on Patterns, and Parallel programming.&lt;/p&gt;  &lt;p&gt;Finishing the week with another day with Rich talking about parallel programming, all using the latest bits of .NET 4.&lt;/p&gt;  &lt;p&gt;Hopefully see you there…&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.software-architect.co.uk" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Speaker_SA2010_360x50" border="0" alt="Speaker_SA2010_360x50" src="http://lh4.ggpht.com/_OxnULoaN7CE/TAjpKB3vy5I/AAAAAAAAAqk/PpkqV3u2Hqo/Speaker_SA2010_360x50%5B4%5D.jpg?imgmax=800" width="244" height="37" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8646374059620055218?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8646374059620055218/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8646374059620055218' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8646374059620055218'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8646374059620055218'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2010/06/software-architecture-2010.html' title='Software Architecture 2010'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_OxnULoaN7CE/TAjpKB3vy5I/AAAAAAAAAqk/PpkqV3u2Hqo/s72-c/Speaker_SA2010_360x50%5B4%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-2913322138003962057</id><published>2010-04-24T10:18:00.001+01:00</published><updated>2010-04-24T10:18:27.697+01:00</updated><title type='text'>Devweek 2011</title><content type='html'>&lt;p&gt;Just heard that Dev Week in London is going to run 14th to 18th March 2011.&amp;#160;&amp;#160; Rock Solid Knowledge will be submitting a variety of talks…If you have some ideas let us know and we will do our best to accommodate.&lt;/p&gt;  &lt;p&gt;And yep I’m sure Dr Rock Man will be back for the drop in consultations.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2913322138003962057?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/2913322138003962057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=2913322138003962057' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2913322138003962057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2913322138003962057'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2010/04/devweek-2011.html' title='Devweek 2011'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-3511313567790335548</id><published>2010-03-25T10:12:00.003Z</published><updated>2010-03-25T10:15:10.740Z</updated><title type='text'>Demos from DevWeek 2010</title><content type='html'>Thanks to everyone who attended any of the Rock Solid Knowledge sessions at DevWeek we now have all our demos available for &lt;a href="http://www.rocksolidknowledge.com/conferences.mvc"&gt;download&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-3511313567790335548?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/3511313567790335548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=3511313567790335548' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3511313567790335548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3511313567790335548'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2010/03/demos-from-devweek-2010.html' title='Demos from DevWeek 2010'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-2702075436619285294</id><published>2010-03-19T16:51:00.001Z</published><updated>2010-03-19T16:51:29.031Z</updated><title type='text'>DevWeek 2010</title><content type='html'>&lt;p&gt;Had a great time again at &lt;a href="http://www.devweek.com"&gt;DevWeek 2010&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All my demos are &lt;a href="http://www.rocksolidknowledge.com/Conferences.mvc/"&gt;uploaded&lt;/a&gt; to our conference page. &lt;/p&gt;  &lt;p&gt;It was the first year we ran our “Ask the Doctor” booth for all those that dropped in I hope you found the advice useful…we certainly had a great time digging into interesting issues, from unit testing, Entity Framework, WCF and general architecture issues..&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2702075436619285294?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/2702075436619285294/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=2702075436619285294' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2702075436619285294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2702075436619285294'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2010/03/devweek-2010.html' title='DevWeek 2010'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-3241539277798126119</id><published>2010-03-11T16:06:00.001Z</published><updated>2010-03-11T16:06:45.608Z</updated><title type='text'>EF4 And Repository Pattern</title><content type='html'>&lt;p&gt;Just released a screencast on one possible way to implement the repository pattern using EF4. I’ve been very down on EF over the past year or so, but its nice at last to see it actually starting to be usable.&lt;/p&gt;  &lt;p&gt;You can listen to this screencast or other RSK screencasts &lt;a href="http://www.rocksolidknowledge.com/screencasts"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-3241539277798126119?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/3241539277798126119/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=3241539277798126119' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3241539277798126119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3241539277798126119'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2010/03/ef4-and-repository-pattern.html' title='EF4 And Repository Pattern'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-7903810114861561910</id><published>2010-02-04T11:09:00.001Z</published><updated>2010-02-04T12:46:11.617Z</updated><title type='text'>Ask the doctor ( Devweek 2010)</title><content type='html'>&lt;pre&gt;Dr Rockman is In!&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;At &lt;a href="http://www.devweek.com" target="_blank"&gt;DevWeek 2010&lt;/a&gt; Rock Solid Knowledge will be running a drop in clinic where our consultants will help you solve your design and development issues.&amp;#160; The whole team will be there so whether its WPF, Silverlight, .NET 4.0, WCF , Design Patterns, Multithreading, Web Development or anything else, we’ll be on hand to lend a sympathetic ear and hopefully solve your problems.&amp;#160; In addition the RSK crew will be delivering pre and post conference days and a whole bunch of sessions which you can see on our &lt;a href="http://www.rocksolidknowledge.com/Conferences.mvc" target="_blank"&gt;conference page&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OxnULoaN7CE/S2qq4t6IAKI/AAAAAAAAAqU/EKSCAzu1WMA/s1600-h/image%5B2%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_OxnULoaN7CE/S2qq5oV1XfI/AAAAAAAAAqY/9m97LN_2DU0/image_thumb.png?imgmax=800" width="142" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-7903810114861561910?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/7903810114861561910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=7903810114861561910' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/7903810114861561910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/7903810114861561910'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2010/02/ask-doctor-devweek-2010.html' title='Ask the doctor ( Devweek 2010)'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_OxnULoaN7CE/S2qq5oV1XfI/AAAAAAAAAqY/9m97LN_2DU0/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6586621841968635898</id><published>2010-02-03T10:56:00.001Z</published><updated>2010-02-03T10:56:11.129Z</updated><title type='text'>Visual Studio Ctrl+Tab Sticking</title><content type='html'>&lt;p&gt;I use Ctrl+Tab inside VS to move between different source files…one day I noticed that when I Ctrl+Tab to the file I wish to view and simply let go of the Ctrl and Tab keys it just sat there, I needed to hit enter to confirm the selection.&amp;#160; This started to get annoying other people had mentioned similar problem.&amp;#160; It seemed to happen when I was training, and finally the penny dropped…..On Windows 7 I use the magnifier via Windows Key and Plus, to highlight bits of code, and then use Windows Key and minus to revert back to normal resolution.&amp;#160; The Magnifier app continues running, it appears that with the magnifier app enabled I have to use Enter to select my file without Ctrl+Tab just works fine…&lt;/p&gt;  &lt;p&gt;So now I close the magnifier app so that Ctrl+Tab continues to work.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6586621841968635898?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6586621841968635898/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6586621841968635898' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6586621841968635898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6586621841968635898'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2010/02/visual-studio-ctrltab-sticking.html' title='Visual Studio Ctrl+Tab Sticking'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-9005723126562487702</id><published>2009-12-01T10:03:00.001Z</published><updated>2009-12-01T10:03:27.993Z</updated><title type='text'>Devweek 2010</title><content type='html'>&lt;p&gt;Rock Solid Knowledge are pleased to announce that we have had a host of talks accepted for &lt;a href="http://www.devweek.com" target="_blank"&gt;Devweek 2010&lt;/a&gt;, including the latest advances in Silverlight, Designing for testing, Enterprise and OO Design Patterns, Workflow and a full day of whats new in .NET 4.&amp;#160; Hope to see you there…&lt;/p&gt;  &lt;p&gt;For a full list of talks &lt;a href="http://www.rocksolidknowledge.com/Conferences.mvc"&gt;click here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-9005723126562487702?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/9005723126562487702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=9005723126562487702' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/9005723126562487702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/9005723126562487702'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/12/devweek-2010.html' title='Devweek 2010'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-4726905440936790528</id><published>2009-10-19T16:43:00.001+01:00</published><updated>2009-10-19T16:43:55.429+01:00</updated><title type='text'>VS2010 Beta 2 Download</title><content type='html'>&lt;p&gt;VS2010 Beta 2 is now available for download for MSN subscribers.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-4726905440936790528?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/4726905440936790528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=4726905440936790528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4726905440936790528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4726905440936790528'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/10/vs2010-beta-2-download.html' title='VS2010 Beta 2 Download'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6639321273049544484</id><published>2009-10-05T14:24:00.001+01:00</published><updated>2009-10-05T14:24:06.029+01:00</updated><title type='text'>Geometric Decomposition Screencast</title><content type='html'>&lt;p&gt;I’ve posted a new screen cast on the Rock Solid Knowledge screen casts side that provides an example of how to partition a set of data for parallel processing.&lt;/p&gt;  &lt;p&gt;The screen cast covers a simple way using Parallel.ForEach, and a more efficient version combining the use of Barrier.&lt;/p&gt;  &lt;p&gt;You can checkout the screen cast and others &lt;a href="http://www.rocksolidknowledge.com/screencasts"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6639321273049544484?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6639321273049544484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6639321273049544484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6639321273049544484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6639321273049544484'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/10/geometric-decomposition-screencast.html' title='Geometric Decomposition Screencast'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-1308038182278811880</id><published>2009-10-05T14:21:00.001+01:00</published><updated>2009-10-05T14:21:44.688+01:00</updated><title type='text'>Parallel utilities</title><content type='html'>&lt;p&gt;Whilst working with .NET 4 parallel extensions I often find the need to extend the framework to assist me in various day to day tasks.&amp;#160; I’ve finally got around to compiling a library of such extensions.&lt;/p&gt;  &lt;p&gt;The extensions include the following&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Set Process Affinity, so I can see how my algorithm scales on a different number of cores.&amp;#160; Will select non hyperthreaded cores first.&lt;/li&gt;    &lt;li&gt;Determine the number of Real cores, not including hyperthreading ones.&lt;/li&gt;    &lt;li&gt;A Range type that supports the partitioning of a range so that I can farm sub ranges out to different tasks&lt;/li&gt;    &lt;li&gt;A Sequence class for building non integer parallel loops or loops with steps other than 1&lt;/li&gt;    &lt;li&gt;Finally a simplified way to handle aggregated exceptions.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You can download the library from &lt;a href="http://rocksolidknowledge.blob.core.windows.net/downloads/ParallelUtilities.zip"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Its a Visual Studio 2010 project, containing the library and a unit test project which should provide enough insight to how the library works.&lt;/p&gt;  &lt;p&gt;Im very keen to know what people think of the aggregate exception handling.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-1308038182278811880?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/1308038182278811880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=1308038182278811880' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1308038182278811880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1308038182278811880'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/10/parallel-utilities.html' title='Parallel utilities'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-1586267789374191916</id><published>2009-10-02T16:54:00.001+01:00</published><updated>2009-10-05T08:59:05.938+01:00</updated><title type='text'>Are Singletons Evil ?</title><content type='html'>&lt;p&gt;Finally got around to delivering a conference talk on this subject this week at &lt;a href="http://www.software-architect.co.uk/"&gt;Software Architecture Week&lt;/a&gt;, its a topic myself and Kevin Jones are constantly being asked.&amp;#160; Of course a quick google reveals the answer there are numerous rants about this evil pattern.&amp;#160; But like most things in life its not as simple as yes or no.&amp;#160; &lt;/p&gt;  &lt;p&gt;Our goal for this talk was to expose the areas were this pattern causes a developer a whole load of pain.&amp;#160; In fact one member of the audience was experiencing such pain in his attempt to take legacy code base heavily utilising singletons and start to write unit tests.&amp;#160; &lt;/p&gt;  &lt;p&gt;So whilst the majority of the time was spent examining the consequences of using the singleton pattern we also took time to&amp;#160; highlight that one or two singletons correctly positioned in your application could in fact enable unit testing, and coding to interface without having to refactor large areas of a legacy code base.&lt;/p&gt;  &lt;p&gt;This talk took the format of a short geeky play, featuring two developers trying to wrestle with getting the job done and unit testing.&amp;#160; You can download the &lt;a href="http://rocksolidknowledge.blob.core.windows.net/demos/Evil+Singleton+Script.pdf"&gt;script&lt;/a&gt; and accompanying &lt;a href="http://rocksolidknowledge.blob.core.windows.net/demos/SA2009+EvilSingleton.zip"&gt;code&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;So like all good consultants our answer to this question is “It Depends”&lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-1586267789374191916?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/1586267789374191916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=1586267789374191916' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1586267789374191916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1586267789374191916'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/10/are-singletons-evil.html' title='Are Singletons Evil ?'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-4010793382963962797</id><published>2009-08-14T07:42:00.001+01:00</published><updated>2009-08-14T07:42:42.758+01:00</updated><title type='text'>Fluent Parallel While</title><content type='html'>&lt;p&gt;During devweek 2009 &lt;a href="http://www.sturmnet.org/blog"&gt;Oliver&lt;/a&gt; introduced me to Fluent Api's, I personally love programs that naturally read, after all programs are read far more often than written.&amp;#160; This week a &lt;a href="http://blogs.msdn.com/pfxteam/archive/2009/08/12/9867246.aspx"&gt;posting&lt;/a&gt; on the Parallel Extensions blog demonstrated how to achieve parallel while, since we only have Parallel.For and Parallel.ForEach&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;   &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            ConcurrentQueue&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; queue = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ConcurrentQueue&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 10; i++)&lt;br /&gt;            {&lt;br /&gt;                queue.Enqueue(i);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;           &lt;br /&gt;            Action&amp;lt;ParallelLoopState&amp;gt; processQueue = (lps) =&amp;gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; item;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (queue.TryDequeue(&lt;span style="color: #0000ff"&gt;out&lt;/span&gt; item))&lt;br /&gt;                {&lt;br /&gt;                    Console.WriteLine(&lt;span style="color: #006080"&gt;&amp;quot; Thread Id = {0} Task Id = {1} : {2}&amp;quot;&lt;/span&gt;, Thread.CurrentThread.ManagedThreadId, Task.Current.Id, item);&lt;br /&gt;                }&lt;br /&gt;            };&lt;br /&gt;&lt;br /&gt;            Func&amp;lt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt;&amp;gt; queueContainsItems = () =&amp;gt; queue.IsEmpty == &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            ParallelUtil.While(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ParallelOptions(), queueContainsItems, processQueue);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I thought I’d combine both these ideas and produce what I would consider a more&amp;#160; Fluent version&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ParallelUtil&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; IEnumerable&amp;lt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt;&amp;gt; Infinite()&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;) &lt;span style="color: #0000ff"&gt;yield&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; ParallelOptions NoParallelOptions = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ParallelOptions();&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; InParallelWhile(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; Action&amp;lt;ParallelLoopState&amp;gt; action, Func&amp;lt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt;&amp;gt; condition, ParallelOptions options = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (options == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) options = NoParallelOptions;&lt;br /&gt;&lt;br /&gt;            Parallel.ForEach(IterateForever(), options , &lt;br /&gt;                (ignored, loopState) =&amp;gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!condition())&lt;br /&gt;                    {&lt;br /&gt;                        loopState.Stop();&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;else&lt;/span&gt;&lt;br /&gt;                    {&lt;br /&gt;                        action(loopState);&lt;br /&gt;                    }&lt;br /&gt;                });&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; IEnumerable&amp;lt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt;&amp;gt; IterateForever()&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;yield&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Program&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Main(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;        {&lt;br /&gt;            ConcurrentQueue&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt; queue = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ConcurrentQueue&amp;lt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 10; i++)&lt;br /&gt;            {&lt;br /&gt;                queue.Enqueue(i);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;           &lt;br /&gt;            Action&amp;lt;ParallelLoopState&amp;gt; processQueue = (lps) =&amp;gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; item;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (queue.TryDequeue(&lt;span style="color: #0000ff"&gt;out&lt;/span&gt; item))&lt;br /&gt;                {&lt;br /&gt;                    Console.WriteLine(&lt;span style="color: #006080"&gt;&amp;quot; Thread Id = {0} Task Id = {1} : {2}&amp;quot;&lt;/span&gt;, Thread.CurrentThread.ManagedThreadId, Task.Current.Id, item);&lt;br /&gt;                }&lt;br /&gt;            };&lt;br /&gt;&lt;br /&gt;            Func&amp;lt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt;&amp;gt; queueContainsItems = () =&amp;gt; queue.IsEmpty == &lt;span style="color: #0000ff"&gt;false&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            processQueue.InParallelWhile(queueContainsItems);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The key difference is the first example you use the following line to process the queue in parallel&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;font face="Courier New"&gt;ParallelUtil.While(new ParallelOptions(), queueContainsItems, processQueue);&lt;/font&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;As opposed to the second version with a perhaps more fluent implementation&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;font face="Courier New"&gt;processQueue.InParallelWhile(queueContainsItems);&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-4010793382963962797?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/4010793382963962797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=4010793382963962797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4010793382963962797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4010793382963962797'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/08/fluent-parallel-while.html' title='Fluent Parallel While'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-3337112004554795471</id><published>2009-07-31T08:08:00.001+01:00</published><updated>2009-07-31T08:08:32.705+01:00</updated><title type='text'>Linq for NHibernate</title><content type='html'>&lt;p&gt;Its been a while coming, but there it is no possible to use LINQ against NHibernate..I think its a shame that MS didn’t get behind the Hibernate family when they first created LINQ as its a marriage made in heaven, combining a mature ORM with a language integrated query.&amp;#160; Rather than spending all that time ( and still ) on trying to create their own ORM.&lt;/p&gt;  &lt;p&gt;I’ve yet to try out the integration, but hopefully will be over the next few weeks…&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ayende.com/Blog/archive/2009/07/26/nhibernate-linq-1.0-released.aspx"&gt;Click Here for the announcement&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-3337112004554795471?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/3337112004554795471/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=3337112004554795471' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3337112004554795471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3337112004554795471'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/07/linq-for-nhibernate.html' title='Linq for NHibernate'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-7689065185619919110</id><published>2009-07-30T11:44:00.002+01:00</published><updated>2009-07-30T12:06:06.540+01:00</updated><title type='text'>WARNING..Cancellation support may makes things go slow….</title><content type='html'>&lt;p&gt;.NET 4 Tasks offers much better support for task cancellation, unlike QueueUserWorkItem tasks can be cancelled before commencing, and the Task library offers a standard way for running tasks to detect and report cancellation.&amp;#160; I recently recorded a &lt;a href="http://www.rocksolidknowledge.com/screencasts"&gt;screencast&lt;/a&gt; that demonstrated the new Task API including the cancellation support.&amp;#160;&amp;#160; This blog post isn’t so much about the cancellation mechanics but some guidance on how best to use it if you don’t want to change the throughput of your task.&lt;/p&gt;  &lt;p&gt;Below is some code that calculates pi, it is expecting to be run inside a task and is supporting the notion of cancellation. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;   &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; AbortableCalculatePi()&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; pi = 1;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; multiplier = -1;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N_ITERATIONS = 500000000;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nIter = 3; nIter &amp;lt; N_ITERATIONS; nIter += 2)&lt;br /&gt;            {&lt;br /&gt;                &lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Task.Current.IsCancellationRequested)&lt;br /&gt;                    {&lt;br /&gt;                        Task.Current.AcknowledgeCancellation();&lt;br /&gt;                        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0.0;&lt;br /&gt;                    }&lt;br /&gt;                &lt;br /&gt;&lt;br /&gt;                pi += (1.0 / (&lt;span style="color: #0000ff"&gt;double&lt;/span&gt;)nIter) * multiplier;&lt;br /&gt;                multiplier *= -1;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; pi * 4.0;&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So all well and good until you benchmark it and compare it to the version with no cancellation support and it runs almost twice as slow.&amp;#160; The reason being that the cost of detecting cancellation is high in relation to the work being done.&amp;#160; The important aspect to cancellation is being able to respond in&amp;#160; a meaningful time for the client, at present we are being way over aggressive in checking.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;One option would be to only check every N iterations..&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; BetterAbortableCalculatePi()&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; pi = 1;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; multiplier = -1;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N_ITERATIONS = 500000000;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nIter = 3; nIter &amp;lt; N_ITERATIONS; nIter += 2)&lt;br /&gt;            {&lt;br /&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((nIter - 3) % 100000 == 0)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Task.Current.IsCancellationRequested)&lt;br /&gt;                    {&lt;br /&gt;                        Task.Current.AcknowledgeCancellation();&lt;br /&gt;                        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0.0;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                pi += (1.0 / (&lt;span style="color: #0000ff"&gt;double&lt;/span&gt;)nIter) * multiplier;&lt;br /&gt;                multiplier *= -1;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; pi * 4.0;&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This&amp;#160; took a third less time than the previous more aggressive version.&amp;#160; However the if block’s effect on the pipeline and the additional maths is still an additional cost over the version that had no cancellation support.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So a third approach is called for this time refactoring the algorithm to use two loops instead of one, were the check for cancellation is done once per iteration of the outerloop, this results in little additional cost.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; OptimisedAbortableCalculatePi()&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; pi = 1;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;double&lt;/span&gt; multiplier = -1;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; N_ITERATIONS = 500000000 / 2;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; OUTER_ITERATIONS = 10000;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;const&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; INNER_ITERATIONS = N_ITERATIONS / OUTER_ITERATIONS;&lt;br /&gt;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; i = 3;&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; outerIndex = 0; outerIndex &amp;lt; OUTER_ITERATIONS; outerIndex++)&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nIter = 0; nIter &amp;lt; INNER_ITERATIONS; nIter++)&lt;br /&gt;                {&lt;br /&gt;                    pi += (1.0 / i) * multiplier;&lt;br /&gt;                    multiplier *= -1;&lt;br /&gt;                    i += 2;&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (Task.Current.IsCancellationRequested)&lt;br /&gt;                {&lt;br /&gt;                    Task.Current.AcknowledgeCancellation();&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; 0.0;&lt;br /&gt;                }&lt;br /&gt;             &lt;br /&gt;            }&lt;br /&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; pi * 4.0;&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here are the timings are got from the various approaches&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;NoAbortableCalculatePi = 3.14159264958921 took 00:00:03.7357873 &lt;br /&gt;  &lt;br /&gt;AbortableCalculatePi = 3.14159264958921 took 00:00:09.6137173 &lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;BetterAbortableCalculatePi = 3.14159264958921 took 00:00:06.3826212 &lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;OptimisedAbortableCalculatePi = 3.14159265758921 took 00:00:03.6883268&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;As the figures show there is virtually no difference between the first and last run, but a considerable difference when cancellation is inserted into the core of the computation.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So to sum up whilst cancellation support is good the frequency you check for could have an impact on the overall performance of your algorithm.&amp;#160; Cancellation is something we want to support but in general users probably don’t need it so we need to strike the right balance between throughput and responding to cancellation in an appropriate timeframe.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-7689065185619919110?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/7689065185619919110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=7689065185619919110' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/7689065185619919110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/7689065185619919110'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/07/warningcancellation-support-may-makes.html' title='WARNING..Cancellation support may makes things go slow….'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6343934717838821287</id><published>2009-07-30T09:49:00.001+01:00</published><updated>2009-07-30T12:00:29.679+01:00</updated><title type='text'>.NET 4 Tasks and UI Programming</title><content type='html'>&lt;p&gt;Just upload a new &lt;a href="http://www.rocksolidknowledge.com/screencasts"&gt;screencast&lt;/a&gt; covering how to marshal results from .NET 4 Tasks back on to the UI thread.&amp;#160; One method is to continue to utilise the same API’s from previous versions of .NET thus utilising SynchronizationContext.Post, the Task based API offers an alternative and in some cases more elegant solution using the ContinueWith method.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6343934717838821287?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6343934717838821287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6343934717838821287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6343934717838821287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6343934717838821287'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/07/net-4-tasks-and-ui-programming.html' title='.NET 4 Tasks and UI Programming'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-5029671162503603147</id><published>2009-07-23T15:15:00.001+01:00</published><updated>2009-07-23T15:15:56.673+01:00</updated><title type='text'>My First Silverlight 3 App</title><content type='html'>&lt;p&gt;Had a brief rest from patterns and parallel stuff to have a quick play with Silverlight 3.&amp;#160; I mainly wanted to see the out of browser aspect, as I think the idea of being able to build RIA that also run on the desktop is very compelling….&lt;/p&gt;  &lt;p&gt;So what to build, I really like the iPhone weather app so I thought I’d have a go at reproducing it in Silverlight, below is a screen shot showing it running out of the browser.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OxnULoaN7CE/Smhwkk6TLRI/AAAAAAAAAYs/xZFy5nJUVHw/s1600-h/image%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_OxnULoaN7CE/SmhwlmjIjeI/AAAAAAAAAYw/XYeFTLLnxKM/image_thumb.png?imgmax=800" width="198" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I’m using isolated storage to store the list of weather centre’s of interest, a more typical line of business app would store app config on the web server/cloud and potentially locally to support true client roaming, but I’ll leave that for another day.&lt;/p&gt;  &lt;p&gt;One thing to note is that the method for enabling Out Of Browser mode for you application is now different from pre-release versions of Silverlight 3, so there are many old blog posts that are unfortunately wrong now.&amp;#160; The good news is now it is trivial, view the project properties, and under the Silverlight tab there is an option to enable the app to support out of browser.&amp;#160; This then creates the OutOfBrowserSettings.xml file.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OxnULoaN7CE/Smhwma5b4WI/AAAAAAAAAY0/qbBhuIe7KSY/s1600-h/image%5B16%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_OxnULoaN7CE/SmhwmyCB7pI/AAAAAAAAAY4/hyO2NIohb_I/image_thumb%5B6%5D.png?imgmax=800" width="342" height="207" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You can download the source via &lt;a href="http://rocksolidknowledge.blob.core.windows.net/downloads/SilverlightWeather.zip?timeout=300"&gt;here&lt;/a&gt; or to just see the app in action click &lt;a href="http://www.rocksolidknowledge.com/weather"&gt;here&lt;/a&gt;.&amp;#160; I’ll let you decide if its as cool as the iPhone….&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-5029671162503603147?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/5029671162503603147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=5029671162503603147' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5029671162503603147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5029671162503603147'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/07/my-first-silverlight-3-app.html' title='My First Silverlight 3 App'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_OxnULoaN7CE/SmhwlmjIjeI/AAAAAAAAAYw/XYeFTLLnxKM/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8998650310582213025</id><published>2009-07-16T18:42:00.001+01:00</published><updated>2009-07-16T19:05:24.913+01:00</updated><title type='text'>Testing on varying number of cores</title><content type='html'>&lt;p&gt;I’ve written many blog articles in the past that show that the performance of a piece of parallel code can vary dramatically based on the number of available cores. With that it mind, its obviously desirable even when given a machine with 8 cores that you test your code against a machine that could have substantially less.&amp;#160; You can resort to task manager and set Process Affinity and reduce the number of cores available for the process, but this is tedious.&amp;#160; There is a .NET API that allows access to controlling which cores to make available for a process.&amp;#160; The API requires the use of a bitmask to identity which cores to use, that's a bit ( no pun intended) overkill for what I'm trying to do, so I created a&amp;#160; facade that allows me to simply say use N cores.&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;   &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Cores&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Max&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Environment.ProcessorCount;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; CoresInUse &lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                IntPtr cores = &lt;br /&gt;                Process.&lt;br /&gt;                    GetCurrentProcess()&lt;br /&gt;                    .ProcessorAffinity;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nCores = 0;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;while&lt;/span&gt;( cores != IntPtr.Zero )&lt;br /&gt;                {&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ( ((&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)cores &amp;amp; 1) == 1 )&lt;br /&gt;                    {&lt;br /&gt;                        nCores++;&lt;br /&gt;                    }&lt;br /&gt;                    cores = (IntPtr)((&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)cores &amp;gt;&amp;gt; 1);&lt;br /&gt;                }&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; nCores;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((&lt;span style="color: #0000ff"&gt;value&lt;/span&gt; &amp;lt; 1) || (&lt;span style="color: #0000ff"&gt;value&lt;/span&gt; &amp;gt; Environment.ProcessorCount))&lt;br /&gt;                {&lt;br /&gt;                    &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ArgumentException(&lt;span style="color: #006080"&gt;&amp;quot;Illegal number of cores&amp;quot;&lt;/span&gt;);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; cores = 1;&lt;br /&gt;                &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; nShift = 0; nShift &amp;lt; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;-1; nShift++)&lt;br /&gt;                {&lt;br /&gt;                    cores = 1 | (cores &amp;lt;&amp;lt; 1);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)cores;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The following code prints out the number of active cores and then reduces the number of cores to 4&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;&lt;br /&gt;  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;Console.WriteLine(&lt;span style="color: #006080"&gt;&amp;quot;Using {0} out of {1}&amp;quot;&lt;/span&gt; , Cores.CoresInUse , Cores.Max);&lt;br /&gt;Cores.CoresInUse = 4;&lt;br /&gt;Console.WriteLine(&lt;span style="color: #006080"&gt;&amp;quot;Using {0} out of {1}&amp;quot;&lt;/span&gt;, Cores.CoresInUse, Cores.Max);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8998650310582213025?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8998650310582213025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8998650310582213025' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8998650310582213025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8998650310582213025'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/07/testing-on-varying-number-of-cores.html' title='Testing on varying number of cores'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8246786142682466081</id><published>2009-07-11T10:51:00.001+01:00</published><updated>2009-07-11T10:51:24.676+01:00</updated><title type='text'>Guerilla .NET Demos from 6th July 2009</title><content type='html'>&lt;p&gt;Had loads of fun as normal teaching Guerilla .NET with Rich and Marcus , All the demos from class &lt;a href="http://www.rocksolidknowledge.com/Download.mvc"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8246786142682466081?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8246786142682466081/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8246786142682466081' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8246786142682466081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8246786142682466081'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/07/guerilla-net-demos-from-6th-july-2009.html' title='Guerilla .NET Demos from 6th July 2009'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-234054834965745851</id><published>2009-06-26T08:26:00.001+01:00</published><updated>2009-06-26T08:26:44.341+01:00</updated><title type='text'>Parallel.For and Parallel.ForEach…moving past Thread.Sleep</title><content type='html'>&lt;p&gt;Just released a screen cast demoing Parallel.For and Parallel.ForEach where we are not demoing the virtues of Parallel Sleep….&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.rocksolidknowledge.com/screencasts"&gt;Click here to see this and many other Rock Solid Knowledge Screen casts&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-234054834965745851?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/234054834965745851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=234054834965745851' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/234054834965745851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/234054834965745851'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/06/parallelfor-and-parallelforeachmoving.html' title='Parallel.For and Parallel.ForEach…moving past Thread.Sleep'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-7348832457973955962</id><published>2009-06-24T13:19:00.001+01:00</published><updated>2009-06-24T13:20:00.000+01:00</updated><title type='text'>Short and Long running tasks in .NET 4</title><content type='html'>&lt;p&gt;Just added a screen cast on how to create short and long running tasks in .NET 4.&amp;#160; You can get to all the Rock Solid Knowledge screen casts via &lt;a href="http://www.rocksolidknowledge.com/screencasts"&gt;www.rocksolidknowledge.com/screencasts&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-7348832457973955962?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/7348832457973955962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=7348832457973955962' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/7348832457973955962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/7348832457973955962'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/06/short-and-long-running-tasks-in-net-4.html' title='Short and Long running tasks in .NET 4'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8879104492652421425</id><published>2009-06-15T19:49:00.001+01:00</published><updated>2009-06-15T19:49:58.766+01:00</updated><title type='text'>Rock Solid Knowledge at Software Architect 2009</title><content type='html'>&lt;p&gt;Just to say that we will be delivering talks at &lt;a href="http://www.software-architect.co.uk/"&gt;Software Architect 2009&lt;/a&gt;, here is a full list of our &lt;a href="http://www.rocksolidknowledge.com/Conferences.mvc"&gt;sessions&lt;/a&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8879104492652421425?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8879104492652421425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8879104492652421425' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8879104492652421425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8879104492652421425'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/06/rock-solid-knowledge-at-software.html' title='Rock Solid Knowledge at Software Architect 2009'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6714077885692627164</id><published>2009-06-15T18:10:00.001+01:00</published><updated>2009-06-15T18:10:45.388+01:00</updated><title type='text'>Long or Short running tasks</title><content type='html'>&lt;p&gt;Been playing around with the new version of Pfx for .NET.&amp;#160; I must say Ive been very impressed with the improvements since the last CTP for .NET 3.5.&amp;#160; So here goes a series of blogs and screen casts on some on various bits of Pfx for .NET 4 BETA 1.&lt;/p&gt;  &lt;p&gt;The one thing that really shouts is that the original&amp;#160; Pfx types are no longer something for just&amp;#160; fine grained parallelism its is a unification of the various threading API’s.&amp;#160; Unifying Api’s is something not new to the .NET framework its been happening since 1.1.&amp;#160; As developers its great that whilst the framework is evolving a constant effort is being made to refactor and simplify previous complexity.&lt;/p&gt;  &lt;p&gt;So previously If&amp;#160; I wanted to create a short running piece of background work I would favour the thread pool, if I was to write a long running piece of background activity I would have to create my own custom thread.&amp;#160;&amp;#160; Creating a short running thread using the thread pool meant either QueueUserWorkItem or Delegate.BeginInvoke, and a long running via new Thread(), and calling Start.&lt;/p&gt;  &lt;p&gt;Now for either types of situation&amp;#160; you simply create a new Task using the new Task type, either via the Task Factory ( not a real GOF Factory, but don’t get me started on that ), or via new Task()&lt;/p&gt;  &lt;p&gt;Task bgTask = Task.Factory.StartNew( MyShortRunningTask);&lt;/p&gt;  &lt;p&gt;For a long running task we use the same API but this time giving it a hint that this is a long running task and shouldn’t therefore use a thread pool thread, but create a new thread outside the thread pool&lt;/p&gt;  &lt;p&gt;Task bgTask = Task.Factory.StartNew( MyLongRunningTask, TaskCreationOptions.LongRunning);&lt;/p&gt;  &lt;p&gt;So too very similar calls but leaving it up to the framework to decide how best to schedule the work.&amp;#160; &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6714077885692627164?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6714077885692627164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6714077885692627164' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6714077885692627164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6714077885692627164'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/06/long-or-short-running-tasks.html' title='Long or Short running tasks'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8290982047326723763</id><published>2009-06-11T14:34:00.001+01:00</published><updated>2009-06-11T14:34:46.039+01:00</updated><title type='text'>VS2010 Edit window outside the IDE</title><content type='html'>&lt;p&gt;Just noticed that I can drag source windows outside the IDE in VS2010, this is something Ive wanted for ages…Now I can really use multiple monitors&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8290982047326723763?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8290982047326723763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8290982047326723763' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8290982047326723763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8290982047326723763'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/06/vs2010-edit-window-outside-ide.html' title='VS2010 Edit window outside the IDE'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-3046195843711500440</id><published>2009-06-10T12:13:00.001+01:00</published><updated>2009-06-10T12:13:37.411+01:00</updated><title type='text'>Pfx team examples moving into the real world</title><content type='html'>&lt;p&gt;I’ve written many articles on my blog about how Im sick of trade show demos of Pfx ( Parallel framework extensions ).&amp;#160; You know the ones using simple Parallel.For with Thread.Sleep or Thread.SpinWait as the piece of work.&amp;#160; These examples scale wonderfully but the moment people take those simple examples and apply them to their own for loops terrible performance often results.&amp;#160; Thankfully the Pfx team have written a blog article offering some suggestions about what to do when the piece of work inside the for loop is too small. ( &lt;a href="http://blogs.msdn.com/pfxteam/archive/2009/06/06/9703059.aspx"&gt;Blog article&lt;/a&gt; ).&amp;#160; Interesting this is the first time I’ve seen them utilise the number of processors in the machine to determine the number of tasks, something I’ve advocated many times in the past for tasks of equal cost.&amp;#160; &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-3046195843711500440?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/3046195843711500440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=3046195843711500440' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3046195843711500440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3046195843711500440'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/06/pfx-team-examples-moving-into-real.html' title='Pfx team examples moving into the real world'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-5109226226362522351</id><published>2009-06-03T19:58:00.001+01:00</published><updated>2009-06-03T19:58:59.690+01:00</updated><title type='text'>Trailing comma in C#</title><content type='html'>&lt;p&gt;Since C# v3 you have been able to initialise collections leaving a trailing comma…&lt;/p&gt;  &lt;p&gt;List&amp;lt;int&amp;gt; vals = new List&amp;lt;int&amp;gt;&lt;/p&gt;  &lt;p&gt;{&lt;/p&gt;  &lt;p&gt;1,&lt;/p&gt;  &lt;p&gt;2,&lt;/p&gt;  &lt;p&gt;3,&lt;/p&gt;  &lt;p&gt;4,&lt;/p&gt;  &lt;p&gt;5,&lt;/p&gt;  &lt;p&gt;};&lt;/p&gt;  &lt;p&gt;I was asking students in a recent class if they liked it or not…One said that he didn’t like the final comma as he thought it suggested something was missing…My original reason for liking them was that it meant I could easily add to the list.&amp;#160; However one student said he liked them as it meant that if you ever did a source control diff on the different versions the diff would only show one line change as opposed to two.&amp;#160; I never thought of that…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-5109226226362522351?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/5109226226362522351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=5109226226362522351' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5109226226362522351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5109226226362522351'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/06/trailing-comma-in-c.html' title='Trailing comma in C#'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-345177794310350892</id><published>2009-05-20T18:48:00.001+01:00</published><updated>2009-05-20T18:48:39.218+01:00</updated><title type='text'>.NET Screencasts</title><content type='html'>&lt;p&gt;Just to say Rock Solid Knowledge of which Im one of the founders have now started to produce a series of screen casts on various bits of .NET technology.&amp;#160; With Beta 1 of VS2010 just out expect a load more in the not too distant future covering all the new goodness&amp;#160; You can checkout the screen casts either via&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.rocksolidknowledge.com/screencasts"&gt;http://www.rocksolidknowledge.com/screencasts&lt;/a&gt; or subscribe via &lt;a href="http://www.rocksolidknowledge.com/screencasts.mvc/RssFeed"&gt;RSS&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-345177794310350892?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/345177794310350892/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=345177794310350892' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/345177794310350892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/345177794310350892'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/05/net-screencasts.html' title='.NET Screencasts'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-655956174373484773</id><published>2009-05-12T15:54:00.001+01:00</published><updated>2009-05-12T15:54:57.458+01:00</updated><title type='text'>Entity Framework and Coarse grain locking</title><content type='html'>&lt;p&gt;I’ve recently had to come back and visit the Entity Framework (EF), as part of this I had the need to provide editing for many entities as a single edit operation.&amp;#160; In effect what I'm really saying here is that my collection of entities is really one entity as far as my user is concerned, e.g. An Order entity is comprised of a series of Order Item entities, as far as the user request is concerned they are editing an order.&lt;/p&gt;  &lt;p&gt;Now out of the box Entity Framework provides support for Optimistic Locking on a per entity basis.&amp;#160; However in my case I don’t want to manage optimistic locking at the level of each EF entity, I wish to do it at the collection/or aggregate level.&amp;#160; There is no direct support for this in EF, so it has to be done by the application developer.&amp;#160; Martin Fowler presents a serious of&amp;#160; patterns for solving this problem which he calls the &lt;a href="http://martinfowler.com/eaaCatalog/coarseGrainedLock.html"&gt;Coarse Grained Lock&lt;/a&gt;.&amp;#160; The Coarse Grained lock is in effect using a single lock for a collection of items, rather than have a lock per item. &lt;/p&gt;  &lt;p&gt;Two possible approaches are put forward one is to nominate a root entity to act as the lock for all other entities, the other is to create a separate entity that represents a shared lock.&lt;/p&gt;  &lt;p&gt;The root entity approach works assuming that from any entity in the aggregate you can easily find and fetch the root entity in order to perform the necessary locking. &lt;/p&gt;  &lt;p&gt;The shared lock approach requires each entity to have a direct reference to the shared lock.&lt;/p&gt;  &lt;p&gt;Neither of these approaches looked especially simple to implement in EF, after playing around with both approaches I finally opted for the shared Optimistic lock pattern.&amp;#160; &lt;/p&gt;  &lt;p&gt;The use case I opted for was a simple one were I’m modelling an Order and a series of Order Items.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OxnULoaN7CE/SgmNu5OpzfI/AAAAAAAAAWM/LRgNyTLo0vU/s1600-h/image%5B8%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_OxnULoaN7CE/SgmNvPOt7LI/AAAAAAAAAWQ/Ak_0j9T8fhI/image_thumb%5B9%5D.png?imgmax=800" width="415" height="111" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; Using simple EF optimistic concurrency I would place a version column in each entity table.&amp;#160; The problem with this is that if two users are editing the same order, by simply modifying different order items or adding items there is no way to ensure that at the end of both edits we have a valid order, since the result in the store will be a merge of both edits whilst each edit session will only see the original and its own changes.&amp;#160; If the two edits were modifying the same order item a concurrency conflict would be detected.&amp;#160; Now in some cases having the ability for two users to edit the same Order concurrently is great, but what if I want to ensure that the composite as a result of both users modifications is in fact valid, perhaps you wish to run some validation logic across the entire composite before saving it.&amp;#160; &lt;/p&gt;  &lt;p&gt;You could start a system transaction per user update, perform the users updates, reload the entire composite, validate it and if it checks out commit the transaction.&amp;#160; However this may be too expensive, and if most of the time there is no contention then this approach is expensive.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OxnULoaN7CE/SgmNvnmNK0I/AAAAAAAAAWU/ara3ixJXdnA/s1600-h/image%5B14%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_OxnULoaN7CE/SgmNwJKnvVI/AAAAAAAAAWY/Ei-nBgA5A-Y/image_thumb%5B13%5D.png?imgmax=800" width="425" height="236" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;By having a shared version across all entities that make up the order we can&amp;#160; be sure that when we save the&amp;#160; parts of the composite that we have changed that the parts that we haven’t changed are still the same.&lt;/p&gt;  &lt;p&gt;When any entity that references a shared version is modified it must update the version entity’s version number, this will only be successfully persisted if the version number in the store is the same as it was when the entity was loaded.&lt;/p&gt;  &lt;p&gt;Now to see if EF can implement this, when building the mappings we end up with an entity for each table, and a reference from the Orders and OrderItems to a Versions Entity. &lt;/p&gt;  &lt;p&gt;The norm in EF when doing optimistic locking is to use a database timestamp column for the version number, in this case this wasn’t possible since we needed to make the version entity be persisted when a change was made to any entity that referenced it, so the version is represented as an integer, when a change is made to any entity that references that version the version number needs to be updated, and thus it will be persisted by EF when we decide to save our changes.&amp;#160; &lt;/p&gt;  &lt;p&gt;All of this could be done manually when ever you load an entity be sure to include the Version its associated with and when you wish to perform a modification increment its associated version, version number.&amp;#160;&amp;#160; This seems tedious and in a production environment missing this step is very likely, the result of which would result in possible corruption assuming two edits happen at the same time.&amp;#160; So I wasn’t happy with that, so what I decided to do was to automate this part of the process.&lt;/p&gt;  &lt;p&gt;Normally in EF you call SaveChanges on the context to persist any changes, the changes are stored in the context and are available to see what has changed, so all I would need to do was to provide my own SaveChanges and look at the change set and for every entity in that set&amp;#160; that references a shared version I increment that version, thus modifying the version and now placing it into the change set.&lt;/p&gt;  &lt;p&gt;Unfortunately you can’t&amp;#160; override &lt;strong&gt;SaveChanges&lt;/strong&gt;, ( apparently you will in EF 2 )&amp;#160; so you end up writing a new method on the ObjectContext in my case I called it &lt;strong&gt;Submit&lt;/strong&gt;, which performs the necessary checks to see what has changed, and then calls SaveChanges.&amp;#160; Note that the type SharedVersion represents the entities in the Version table.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; AcmeWidgets&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Submit()&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;{&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="rem"&gt;// Establish all the entities that have changed&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="rem"&gt;//&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    var entities = &lt;span class="kwrd"&gt;this&lt;/span&gt;.ObjectStateManager&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        .GetObjectStateEntries(EntityState.Modified | EntityState.Added );&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    var toIncrement = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;, SharedVersion&amp;gt;();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="rem"&gt;// Foreach entity that has changed, if it has a shared version&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="rem"&gt;// then increment it.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ObjectStateEntry attachedObject &lt;span class="kwrd"&gt;in&lt;/span&gt; entities.Where(e =&amp;gt; e.IsRelationship == &lt;span class="kwrd"&gt;false&lt;/span&gt; ) )&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;    {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        &lt;span class="rem"&gt;// If No property of type SharedVersion then it will not attempt to increment the version&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;        &lt;span class="rem"&gt;// if many it will throw an exception&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;        &lt;span class="rem"&gt;// if just one will increment the version number, assuming it has not &lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;        &lt;span class="rem"&gt;// previously been incremented&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        PropertyInfo versionProperty = (from prop &lt;span class="kwrd"&gt;in&lt;/span&gt; attachedObject.Entity.GetType().GetProperties()&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;                                        &lt;span class="kwrd"&gt;where&lt;/span&gt; prop.PropertyType == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(SharedVersion)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;                                        select prop)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;                                        .DefaultIfEmpty(&lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;                                        .Single();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (versionProperty != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;        {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;            SharedVersion versionEntity = (SharedVersion) versionProperty.GetValue(attachedObject.Entity, &lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (versionEntity != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;            {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (!toIncrement.ContainsKey(versionEntity.id))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;                {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;                    toIncrement.Add(versionEntity.id, versionEntity);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;                    versionEntity.Increment();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;                }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;            }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;            {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; SharedVersionException(&lt;span class="str"&gt;&amp;quot;You must load the version of the entity if you wish to modify it&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;            }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;        }     &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;    &lt;span class="rem"&gt;// Now call down to the entity framework to do persist&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;    &lt;span class="rem"&gt;// any version entities used will now be marked.&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;    SaveChanges();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In addition to my own Submit method, I also needed to write strongly typed Delete methods on the context, so that if the final part of the composite was deleted the version entity associated with the composite would also be deleted.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Finally it would be nice to automatically assign the version reference to any new object that becomes part of the composite.&amp;#160; To do this I register for change on the OrderItems collection of the order and assign it the same version object of the Order its part of.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Order&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Order()&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.OrderItems.AssociationChanged += &lt;span class="kwrd"&gt;new&lt;/span&gt; System.ComponentModel.CollectionChangeEventHandler(OrderItems_AssociationChanged);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="kwrd"&gt;void&lt;/span&gt; OrderItems_AssociationChanged(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, System.ComponentModel.CollectionChangeEventArgs e)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.Action == System.ComponentModel.CollectionChangeAction.Add)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;        {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;            OrderItem item = (OrderItem)e.Element;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (item.Version == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;            {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;               item.Version = &lt;span class="kwrd"&gt;this&lt;/span&gt;.Version;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;            }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.Action == System.ComponentModel.CollectionChangeAction.Remove)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;        {&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.Version.Increment();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The last part and probably the bit I like least is the fact that you need to ensure that for every entity that is loaded you must insure that the associated version entity is loaded at the same time.&amp;#160; This can’t be lazily loaded as its important to know the entity and associated version are in step with each other.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="csharpcode"&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt; Order order = ctx.OrderSet&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;                    .Include(&lt;span class="str"&gt;&amp;quot;Version&amp;quot;&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;                    .Include(&lt;span class="str"&gt;&amp;quot;OrderItems&amp;quot;&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;                    .Include(&lt;span class="str"&gt;&amp;quot;OrderItems.Version&amp;quot;&lt;/span&gt;)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;                    .First();&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So whilst this all works, its a real shame coarse grained locking has not been considered by the framework providers, EF is at best an ok ORM for simple entities but fails to support out of the box moderately complex real world examples.&amp;#160; I think its having to go to this level of effort that still puts developers off betting on a ORM.&amp;#160; All the code can be downloaded from &lt;a href="http://rocksolidknowledge.blob.core.windows.net/downloads/EFConcurrencyCourseGrain.zip"&gt;here&lt;/a&gt;.&amp;#160; Note the database creation script is for SQL 2008.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-655956174373484773?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/655956174373484773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=655956174373484773' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/655956174373484773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/655956174373484773'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/05/entity-framework-and-coarse-grain.html' title='Entity Framework and Coarse grain locking'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_OxnULoaN7CE/SgmNvPOt7LI/AAAAAAAAAWQ/Ak_0j9T8fhI/s72-c/image_thumb%5B9%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-2750553660198355104</id><published>2009-04-01T16:05:00.001+01:00</published><updated>2009-04-01T16:05:23.341+01:00</updated><title type='text'>Microsoft's Parallel Framework extensions (Pfx) isn’t always the free lunch its cracked up to be.</title><content type='html'>&lt;p&gt;I’ve seen numerous demos of Microsoft's Parallel Framework Extensions ( Pfx), and as you would expect they focus on showing how easy it is to make sequential code go faster on multiple cores.&amp;#160; Whilst there is no disputing that the code that is run certainly scales as you add new processors, you can’t get away from the fact that a lot of these demos are contrived, heavy use of Thread.SpinWait to simulate lots of computation for each parallel task.&amp;#160;&amp;#160; Take away the SpinWait and do some simple one line piece of computation and you will almost certainly end up with a far worse performance than you had with sequential approach.&amp;#160; The reason being that creating , scheduling and correlating results is not free.&amp;#160; So when deciding to utilise Pfx you need to ensure that you each piece of parallel activity is sufficient in size to benefit from the additional cores.&amp;#160; This is were the problem lies whilst its easy to drop in a Thread.SpinWait for demo purposes its often not easy to take your piece of real world computation you wish to parallelise and make each piece parallel activity be of significant size.&lt;/p&gt;  &lt;p&gt;One demo I’ve seen over and over again is summing the nodes of a binary tree. The sequential version looks like this&lt;/p&gt;  &lt;p&gt;private static int SumTree(Node root)    &lt;br /&gt;{ &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return root.Value + (root.Left == null ? 0 : SumTree(root.Left)) + (root.Right == null ? 0 : SumTree(root.Right));    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;This could then be parallelised&amp;#160; like so&lt;/p&gt;  &lt;p&gt;private static int ParallelSumTree(Node root)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int lhsTotal = 0;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int rhsTotal = 0; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Future&amp;lt;int&amp;gt; lhs = Future&amp;lt;int&amp;gt;.Create(() =&amp;gt; root.Left == null ? 0 : ParallelSumTree(root.Left));    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Future&amp;lt;int&amp;gt; rhs = Future&amp;lt;int&amp;gt;.Create(() =&amp;gt; root.Right == null ? 0 :ParallelSumTree(root.Right));     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; lhsTotal = lhs.Value;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; rhsTotal = rhs.Value;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return root.Value + lhsTotal + rhsTotal;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;  &lt;p&gt;Future&amp;lt;T&amp;gt; is a Pfx type that is used to create a parallel task that yields a result in this case an int.&amp;#160; The instance of Future&amp;lt;T&amp;gt; has a Value property that you can use to get the result of the parallel task. If you request the Value and the task has not yet completed&amp;#160; you block waiting for the result.&amp;#160; I personally really like this model but they have scrapped this type in .NET 4.0 release of Pfx and have the concept that a parallel task can return a value as opposed to void.&lt;/p&gt;  &lt;p&gt;This form of parallelisation can work if the computation of both of the futures takes a reasonable time.&amp;#160; To demonstrate this I have an implementation that allows the amount of computation to vary, utilising a for…loop.&amp;#160; I varied the length of the loop from 0 to 50,000 iterations.&amp;#160; With the case of 0 iterations simulating the real task in hand to sum all nodes in the binary tree, and 50,000 to simulate a more expensive operation to perform on each node.&amp;#160; I ran the code over a binary tree of 500k nodes with 2 cpus.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OxnULoaN7CE/SdOCovZQvUI/AAAAAAAAACU/T-QP9H3DePo/s1600-h/image%5B7%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_OxnULoaN7CE/SdOCpCSIpxI/AAAAAAAAACY/m5oKMqYX7DY/image_thumb%5B3%5D.png?imgmax=800" width="474" height="280" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;What the result shows is that you need to have a workload equivalent to 42k loop iterations for the parallel version to be faster, but note not twice as fast.&amp;#160; I then ran the same piece of code on a 8 core machine, here the point in which the parallel version was more effective was around 10k loop iteration mark.&amp;#160; This shows that the size of the workload to be effective for parallelisation is also a function of the number of available cores.&amp;#160; Today you may well rule out a parallel variant of an algorithm as it doesn’t offer a speed up, whilst in the future when we have say 32+ cores it may well do so, which is why the MS guys are keen to advocate you build for future concurrency not necessarily what you have today.&amp;#160;&amp;#160; However we obviously don’t want to have a slower parallel version today for the possibility of some future benefit.&amp;#160; The reason for this speed up as we add more cores means we run more code in parallel this is not only our algorithm but also the task creation code.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OxnULoaN7CE/SdOCp3diGFI/AAAAAAAAACc/eQVuMYsAW-M/s1600-h/image%5B19%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_OxnULoaN7CE/SdOCqdFCppI/AAAAAAAAACg/DpswUxNoM_g/image_thumb%5B9%5D.png?imgmax=800" width="482" height="301" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;The eight processor version is a lot more compelling than the two processor version, however I'm not comfortable with this, as the speed up&amp;#160; I’m getting is not close to 8x speed up which is what the ideal case would be, in fact it is at best about 4 times.&amp;#160; In some cases it may be reasonable to accept this, as the effort to make the 4x speed up was very little work, and if we wait a while until we have say 32 procs we will continue to get a speed up just in the same way we did in the past with greater clock speed.&lt;/p&gt;  &lt;p&gt;If you do want to squeeze every last drop out of the machine then you will need to think of ways to optimise the algorithm so that the overhead of parallelisation is reduced.&amp;#160; In this case its about not having to manage lots of separate tasks.&amp;#160; For this algorithm a couple of things stand out that will help here.&amp;#160; &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;The tree is perfectly balanced&lt;/li&gt;    &lt;li&gt;The computation for each node is identical&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;We can take advantage of these two facts along with the knowledge of how many cores we currently have available, and simply divide the tree up between all the cores.&amp;#160; That way we take minimal hit for task creation, and each core can run flat out on its given piece of work, and since all work items are equal we would expect all cores to be utilised the same.&amp;#160; The two graphs below show this new implementation which has a far better performance.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_OxnULoaN7CE/SdOCq7rBMgI/AAAAAAAAACk/WTY9LsB1Q_o/s1600-h/image%5B26%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_OxnULoaN7CE/SdOCrdw1A-I/AAAAAAAAACo/fERahJFvqiI/image_thumb%5B12%5D.png?imgmax=800" width="478" height="282" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_OxnULoaN7CE/SdOCrhoGizI/AAAAAAAAACs/s8JIeBF-quk/s1600-h/image%5B27%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_OxnULoaN7CE/SdOCsmhnj5I/AAAAAAAAACw/WkCw9qU7DmM/image_thumb%5B13%5D.png?imgmax=800" width="482" height="301" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The two above facts about the tree made producing an efficient parallel implementation reasonably easy.&amp;#160; If you had a unbalanced tree it may be worth balancing it or producing a series of other containers that contain the collection of nodes spread evenly.&amp;#160; For this to be effective the computational work has to be of&amp;#160; greater than the cost of scanning the tree. Alternatively a more dynamic approach could be undertaken were by the algorithm kept track of how many cores it was utilising and when it detected full utilisation it keeps all new activities on the same core as part of the same task.&amp;#160; It is often worth considering parallelisation when deciding how to structure your data.&lt;/p&gt;  &lt;p&gt;Conclusion&lt;/p&gt;  &lt;p&gt;Parallel.For and use of lots of tasks will not necessarily make your code go faster, it may well go slower.&amp;#160; The piece of work being parallelised must be of sufficient size to benefit from the overhead of parallel framework and finding that piece of work is often not as easy as you might expect.&amp;#160; Going forward as machines have greater and greater number of cpu’s that size of computation necessary to take advantage of the framework will get less.&amp;#160; However&amp;#160; this will not always result in the most effective us of the cores.&amp;#160; If you want to take full advantage of the cores to get maximum performance you will need to structure the algorithm so that understands the environment that it is running in, in order to best utilise resources, and it is this part that often requires the hard thinking.&amp;#160; So is the free lunch back?&amp;#160; Well to some degree if you want an ok lunch, but for a gut busting lunch you will still have to work for it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2750553660198355104?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/2750553660198355104/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=2750553660198355104' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2750553660198355104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2750553660198355104'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/04/microsoft-parallel-framework-extensions.html' title='Microsoft&amp;#39;s Parallel Framework extensions (Pfx) isn’t always the free lunch its cracked up to be.'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_OxnULoaN7CE/SdOCpCSIpxI/AAAAAAAAACY/m5oKMqYX7DY/s72-c/image_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-5512375360745685900</id><published>2009-03-29T20:50:00.001+01:00</published><updated>2009-03-29T20:50:04.551+01:00</updated><title type='text'>Ruby Ranges in .NET</title><content type='html'>&lt;p&gt;Managed to attend some talks whilst I was at &lt;a href="http://www.devweek.com"&gt;DevWeek 2009&lt;/a&gt;, one such talk was by &lt;a href="http://www.sturmnet.org/blog/"&gt;Oliver Sturm&lt;/a&gt; on the topic of other cool stuff you can do with C# v3 other than Linq.&amp;#160; Really enjoyed the talk introduced me to topics like Fluent Api's.&amp;#160; If a series of types have a fluent API they allow you to build up code that reads more like a regular sentence.&lt;/p&gt;  &lt;p&gt;E.g. invoices.All.OverDueBy(30.Days).SendReminders();&lt;/p&gt;  &lt;p&gt;One of the demo's Oliver did was to show a C# implementation of a standard Ruby technique called Ranges.&lt;/p&gt;  &lt;p&gt;numbers = [ 1..10]&lt;/p&gt;  &lt;p&gt;Here the numbers variable represents all values between 1 and 10.&amp;#160; Some obvious things you would like to do with the range is consume it via foreach, or in Ruby speak Each, or determine if a given value is inside the range.&lt;/p&gt;  &lt;p&gt;Oliver took based his implementation from &lt;a href="http://www.pluralsight.com/community/blogs/dbox/archive/2005/04/24/7690.aspx"&gt;Don Box's&lt;/a&gt; implementation and modified a few bits..&amp;#160; Don's implementation is based on .NET 2.0 generics and thus when he builds a Range&amp;lt;T&amp;gt; type you are required to provide delegate instances that provide the next item in the range and determine if a given value is inside the range.&amp;#160; So that your don't have to provide delegate instances for the basic primitive types Don supplied a series of static helper methods that supply the necessary delegate instances.&lt;/p&gt;  &lt;p&gt;I started thinking if this was necessary in C# 3, could we not use the new Expression syntax to automatically build the ranges without the need to supply delegate instances.&amp;#160; The idea is that the Range&amp;lt;T&amp;gt; builds the necessary delegate instances by building expressions, I blogged about this technique a while back that whilst you can't do numeric operations on T as part of standard generics you can build expressions on T that you can attempt to perform an Add operation on.&amp;#160; &lt;/p&gt;  &lt;p&gt;Based on the previous experience of building a Generic Sum method using Expressions I got to work and built an implementation of Range&amp;lt;T&amp;gt; that attempts to build the the necessary next and isIn delegate instances for you.&lt;/p&gt;  &lt;p&gt;public class Range&amp;lt;T&amp;gt; : IEnumerable&amp;lt;T&amp;gt;   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public T Start { get; private set; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public T End { get; private set; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; private Func&amp;lt;T, T&amp;gt; next;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private Func&amp;lt;T, bool&amp;gt; isIn; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public Range(T start, T end, T step)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; : this(start, end, step, false)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; { &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public Range(T start, T end, T step, bool highToLow)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; InitStartAndEnd(start, end); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ParameterExpression current = Expression.Parameter(typeof(T), &amp;quot;current&amp;quot;); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression&amp;lt;Func&amp;lt;T, T&amp;gt;&amp;gt; nextExpr = Expression.Lambda&amp;lt;Func&amp;lt;T, T&amp;gt;&amp;gt;(   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.Add(    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; current,    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.Constant(step)),    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; current); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; isInExpr = null; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (highToLow)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; isInExpr = Expression.Lambda&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt;(    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.And(    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.GreaterThanOrEqual(current, Expression.Constant(end)),    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.LessThanOrEqual(current, Expression.Constant(start))),    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; current);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; isInExpr = Expression.Lambda&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt;(    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.And(    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.GreaterThanOrEqual(current, Expression.Constant(start)),    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Expression.LessThanOrEqual(current, Expression.Constant(end))),    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; current);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; isIn = isInExpr.Compile();   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; next = nextExpr.Compile();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public Range(T start, T end, Func&amp;lt;T, T&amp;gt; next, Func&amp;lt;T, bool&amp;gt; isIn)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; InitStartAndEnd(start, end);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.next = next;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.isIn = isIn;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public bool IsIn(T val)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return isIn(val);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public override string ToString()   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return String.Format(&amp;quot;{0}..{1}&amp;quot;, Start, End);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; private void InitStartAndEnd(T start, T end)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Start = start;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End = end;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; public IEnumerator&amp;lt;T&amp;gt; GetEnumerator()   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; T current = Start;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield return current; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; while (isIn(current))   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; current = next(current);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield return current;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return GetEnumerator();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;}&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;With this type defined you now write code like this&lt;/p&gt;  &lt;p&gt;var digits = new Range&amp;lt;int&amp;gt; (0,9,1);&lt;/p&gt;  &lt;p&gt;I can now consume all the digits via a simple foreach loop, or perhaps use the range as part of a Linq expression since my Range&amp;lt;T&amp;gt; implements IEnumerable&amp;lt;T&amp;gt;.&lt;/p&gt;  &lt;p&gt; digits.Except( new&amp;#160; int[] { 0,2,4,6,8 } ).ToList().ForEach( i=&amp;gt;Console.WriteLine(i) );&lt;/p&gt;  &lt;p&gt;This will print out all the odd numbers from the range..&lt;/p&gt;  &lt;p&gt;With the addition of another C# v3 feature extension methods, we can write a &amp;quot;fluent api&amp;quot; style method.&lt;/p&gt;  &lt;p&gt;public static class RangeUtil   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; { &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public static bool In&amp;lt;T&amp;gt;(this T val, Range&amp;lt;T&amp;gt; range)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return range.IsIn(val);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;I can now write &lt;/p&gt;  &lt;p&gt;bool isSingleDigitValue =&amp;#160; 5.In( digits ) ;&lt;/p&gt;  &lt;p&gt;I really wanted to support enumerations without the need to define your own next and IsIn delegate instances but couldn't quite get there.&amp;#160; Im sure its possible with a bit more thought.&amp;#160; But for now enum ranges need to be defined by creating a new type derived from the Range&amp;lt;T&amp;gt; type.&lt;/p&gt;  &lt;p&gt;public enum Places { First, Second, Third, Fourth }; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; public class PlacesRange : Range&amp;lt;Places&amp;gt;   &lt;br /&gt;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public PlacesRange(Places start, Places end)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; : base(start, end, p =&amp;gt; p + 1, p =&amp;gt; p&amp;gt;= start &amp;amp;&amp;amp; p &amp;lt;=end )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }   &lt;br /&gt;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;Note this only works if there are no gaps in the enumeration values.&lt;/p&gt;  &lt;p&gt;There are other situations were the normal Add operator is not sufficient&lt;/p&gt;  &lt;p&gt;public class DayRange : Range&amp;lt;DateTime&amp;gt;   &lt;br /&gt;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public DayRange(DateTime start, DateTime end )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; : base(start.Date, end.Date, d =&amp;gt; d.AddDays(1), d =&amp;gt; d &amp;gt;= start &amp;amp;&amp;amp; d &amp;lt;= end )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }   &lt;br /&gt;&amp;#160; } &lt;/p&gt;  &lt;p&gt;To use the DayRange type &lt;/p&gt;  &lt;p&gt;DayRange days = new DayRange(new DateTime(2009, 1, 1), new DateTime(2009, 12, 30)); &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (DateTime.Now.In(days))   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Console.WriteLine(&amp;quot;You are in Year 2009&amp;quot;);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;In conclusion Ranges do look pretty cool..however it should be noted that using ranges to represent a simple iteration is far more expensive than a normal for loop, but they are great for building fluent api’s.&lt;/p&gt;  &lt;p&gt;You can download the complete source &lt;a href="http://rocksolidknowledge.blob.core.windows.net/downloads/Ranges.zip"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-5512375360745685900?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/5512375360745685900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=5512375360745685900' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5512375360745685900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5512375360745685900'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/03/ruby-ranges-in-net.html' title='Ruby Ranges in .NET'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-707651545624678689</id><published>2009-03-26T18:21:00.001Z</published><updated>2009-03-26T18:21:00.913Z</updated><title type='text'>Devweek 2009</title><content type='html'>&lt;p&gt;Just posted all my demos from my sessions at devweek, checkout all the Rock Solid Knowledge guys demos via &lt;a href="http://www.rocksolidknowledge.com/Conferences.mvc"&gt;Rock Solid Knowledge Conferences&lt;/a&gt;.&amp;nbsp; Also just like to say what a fantastic conference Devweek is, met loads of interesting people and had a lot of fun delivering the talks.&amp;nbsp; Patterns Dartboard worked out really well...Tim tried hard to get me to consider moving to Ruby...and Oliver scared me with F#...&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-707651545624678689?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/707651545624678689/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=707651545624678689' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/707651545624678689'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/707651545624678689'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/03/devweek-2009.html' title='Devweek 2009'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8913403055936283124</id><published>2009-02-19T13:07:00.001Z</published><updated>2009-02-19T13:07:31.872Z</updated><title type='text'>New email client</title><content type='html'>&lt;p&gt;Im sure its not just me but outlook has always seemed very sluggish...and this week I had finally had enough when it stopped synchronising with my IMAP inbox folder...So I reverted back to using Mozilla Thunderbird...And boy its so much sleeker...&lt;/p&gt; &lt;p&gt;Install took seconds...and best of all with a couple of free addins it&amp;nbsp; fully integrates with google calendar and contacts, which is perfect for me especially since I have my iPhone sync directly with google calendar and contacts via a great free service &lt;a href="http://www.nuevaSync.com"&gt;www.nuevaSync.com&lt;/a&gt;.&amp;nbsp; This removes the need to sync my iPhone except for Media content...My contacts and calendar are sync'd all the time..&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8913403055936283124?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8913403055936283124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8913403055936283124' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8913403055936283124'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8913403055936283124'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/02/new-email-client.html' title='New email client'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-7157496585888803351</id><published>2009-01-06T19:43:00.001Z</published><updated>2009-01-06T19:43:27.812Z</updated><title type='text'>Power Point Merge</title><content type='html'>&lt;p&gt;Im currently preparing my slide decks for &lt;a href="http://www.devweek.com"&gt;Dev Week 2009&lt;/a&gt;, and for the day of design patterns Im having to merge five individual decks to make a single deck, now I could do this by hand or I could write a tool to do, and since Ive managed to get the hang of the power point automation api I did just that.&amp;nbsp; You can download the tool from &lt;a href="http://www.beaconsoft.co.uk/Download.mvc/Download/32432bd7-162e-4684-8299-dbd2be8c981b"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-7157496585888803351?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/7157496585888803351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=7157496585888803351' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/7157496585888803351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/7157496585888803351'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2009/01/power-point-merge.html' title='Power Point Merge'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-5243814082590457005</id><published>2008-12-18T16:59:00.001Z</published><updated>2008-12-18T16:59:36.013Z</updated><title type='text'>Design Patterns Crossword</title><content type='html'>&lt;p&gt;Whilst teaching Developmentors &lt;a href="http://www.develop.com/course/net-design-patterns"&gt;"Code Smarter with Design Patterns in .NET"&lt;/a&gt; class a student pointed me towards this Gang of Four patterns crossword puzzle.&amp;nbsp; To test your GOF patterns &lt;a href="http://www.vokamis.com/products/cword/app/enterGame.php?ns=/a/a&amp;amp;or=V&amp;amp;h=128&amp;amp;pub=2 "&gt;click here&lt;/a&gt; Enjoy!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-5243814082590457005?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/5243814082590457005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=5243814082590457005' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5243814082590457005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5243814082590457005'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/12/design-patterns-crossword.html' title='Design Patterns Crossword'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-2613780683161918575</id><published>2008-12-18T16:47:00.001Z</published><updated>2008-12-18T16:47:09.639Z</updated><title type='text'>Sql Server 2008 and TransactionScope just got better</title><content type='html'>&lt;p&gt;Its hard to deny that the TransactionScope programming model created in .NET 2.0 was pretty cool.&amp;nbsp; Initial feelings when I saw it was wow I can now place transactional directives in the business layer and have everything inside that block right down to the data layer enlist in the transaction.&amp;nbsp; However disappointment was only just around the corner when you saw that multiple Open/Close pairs inside the same transaction caused the transaction to be promoted to the DTC ( &lt;a href="http://andyclymer.blogspot.com/2007/01/transactionscope-and-dataadapters.html"&gt;see previous post&lt;/a&gt; ) event though you were talking to the same database instance.&lt;/p&gt; &lt;p&gt;There have been many solutions to this problem, all effectively resulting in changing the way your data layer works to maintain an open connection across multiple data access layer calls.&amp;nbsp; My implementation can be found &lt;a href="http://www.beaconsoft.co.uk/Download.mvc/Download/c66ae40b-84a1-4a76-b96c-f39d344699c4"&gt;here&lt;/a&gt;, and Alazel Acheson's &lt;a href="http://blogs.msdn.com/dataaccess/attachment/532026.ashx"&gt;here&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The good news is that this is no longer needed as of Sql Server 2008, the transaction is only promoted when you do indeed involve multiple resources.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2613780683161918575?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/2613780683161918575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=2613780683161918575' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2613780683161918575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2613780683161918575'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/12/sql-server-2008-and-transactionscope.html' title='Sql Server 2008 and TransactionScope just got better'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6098213704097538518</id><published>2008-11-19T10:41:00.001Z</published><updated>2008-11-19T10:41:13.865Z</updated><title type='text'>Power point to Microsoft One Note</title><content type='html'>&lt;p&gt;I often find the need to produce a one note book of a set of slides so that I can annotate and scribble notes against a given slide.&amp;nbsp; In the past Ive imported the slides manually into a one note book, I finally got around to building a tool that automates the process.&amp;nbsp; You can download it from &lt;a href="http://www.beaconsoft.co.uk"&gt;http://www.beaconsoft.co.uk&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6098213704097538518?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6098213704097538518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6098213704097538518' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6098213704097538518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6098213704097538518'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/11/power-point-to-microsoft-one-note.html' title='Power point to Microsoft One Note'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6559525991840212067</id><published>2008-10-28T13:58:00.001Z</published><updated>2008-10-28T13:58:41.277Z</updated><title type='text'>PDC 2008, Day one</title><content type='html'>&lt;p&gt;This is my first PDC, so not sure what to expect in terms of quality of speakers and content.&amp;nbsp; Key note on cloud services the new windows platform Windows Azure was a little disappointing based on the fact that it was a developer audience.&amp;nbsp; In essence Microsoft are providing a platform for other companies to take advantage of large distributed data centres.&amp;nbsp; Microsoft has some experience in this space in providing Windows Update, MSDN content , Hotmail , Live services, these services will be ported to the new platform to allow them to self validate the platform, and offer others the ability to out source the data centre services.&amp;nbsp;&amp;nbsp;&amp;nbsp; There will be a short period of time were these services will be free, but in 2009 MS will start to charge for the cloud services based on usage and SLA.&amp;nbsp; Google's cloud based computing has been a serious threat to MS traditional inside the enterprise model, companies have started looking to outsource basic IT, Daily Telegraph recently announced the use of Google for email and office based apps..Its still yet to be seen if large corporations with lots of IPR will ever rely on a third party to hold and manage their data, and this fact plays nicely into Microsoft's offering as they have concentrated on allowing enterprises to utilise the cloud with existing applications inside the enterprise, thus enabling perhaps companies to shift over time, and deciding what is ok to put into the cloud.&amp;nbsp; This is a key advantage they have over the google offering...Other key advantages is that as an MS developer I continue to use the same tools and languages to target the cloud as I do inside the enterprise, and thats huge.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Whilst all that fluffy cloud stuff was interesting, for me the best talk was on C# 4.0 by Anders.&amp;nbsp; Anders is not only a seriously smart guy but a great presenter too.&amp;nbsp; The high lights where&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Dynamic language feature support&lt;/p&gt; &lt;p&gt;Co-variance on generic interfaces&lt;/p&gt; &lt;p&gt;Default/Optional parameters &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The dynamic language support was very cool..&amp;nbsp; Microsoft has been working on a DLR ( Dynamic Language Runtime ) for some time to make it easier to write dynamic languages, IronPython and IronRuby utilise common functionality to deliver dynamic language behaviour.&amp;nbsp; C# will now utilise some of that same functionality, by introducing the dynamic keyword.&amp;nbsp; So I can write&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;dynamic foo = 10&lt;/p&gt; &lt;p&gt;foo = "hello"&lt;/p&gt; &lt;p&gt;foo = 5.6&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;When you call a method on foo it is late bound, this late binding is done by the fact that foo is of type DynamicObject which has various methods on it like GetMember , InvokeMethod which take a string to represent a Member/Method name.&amp;nbsp; The main aim of this is to allow better interop between staticly typed languages and dynamic ones.&amp;nbsp; Thus calling java script from silverlight is now something like this&lt;/p&gt; &lt;p&gt;&amp;lt;h1 id="title"&amp;gt;Hello&amp;lt;/h1&amp;gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;dynamic element = HtmlPage.Document.title;&lt;/p&gt; &lt;p&gt;element.innerText = "Good Bye";&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Also COM interop via this mechanism means no PIA's.&amp;nbsp; and a programming model that looks very easy to consume.&amp;nbsp; It also has massive ramifications for Active Record pattern utilised by Ruby on Rails, and for processing XML documents using a dot notation that matches the names of elements.&amp;nbsp; The creation of REST proxies would also seem extremely straight forward.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Support for co-variance List&amp;lt;string&amp;gt; can now be turned into an IEnumerable&amp;lt;object&amp;gt;.&amp;nbsp; Something that has been very frustrating in the past.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Finally we can write C# methods &lt;/p&gt; &lt;p&gt;public int Add( int lhs = 1, int rhs = 1 )&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;We can therfore call Add(), Add(1) and Add(1,1) to produce the same result or&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Add( rhs: 1 , lhs : 1 )&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Day 2 is now calling...so hopefully plenty of goodness coming&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6559525991840212067?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6559525991840212067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6559525991840212067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6559525991840212067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6559525991840212067'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/10/pdc-2008-day-one.html' title='PDC 2008, Day one'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6838716124201243690</id><published>2008-10-01T10:26:00.001+01:00</published><updated>2008-10-01T10:26:33.757+01:00</updated><title type='text'>WARNING...Look after your speakers badge</title><content type='html'>&lt;p&gt;I noticed today that there is a site called &lt;a href="http://www.whereisandyclymer.com/"&gt;http://www.whereisandyclymer.com/&lt;/a&gt; and so I clicked on it...and yo and behold its a series of strange locations featuring my Speakers card from Software Architecture week.&amp;nbsp; A quick whois lookup revealed the culprit a fellow Developmentor instructor....&lt;/p&gt; &lt;p&gt;Think I'll be looking after my speaker badge in future...&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6838716124201243690?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6838716124201243690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6838716124201243690' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6838716124201243690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6838716124201243690'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/10/warninglook-after-your-speakers-badge.html' title='WARNING...Look after your speakers badge'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-500183066891632065</id><published>2008-10-01T08:48:00.001+01:00</published><updated>2008-10-01T08:48:40.049+01:00</updated><title type='text'>Random Sampling extension method</title><content type='html'>&lt;p&gt;Had reason recently to select a random sample of data from a stream of elements.&amp;nbsp; The amount of samples I needed to take was finite but what was unknown was the number of elements in the input stream.&amp;nbsp; I managed to find various implementations of an IEnumerable extension method on the net, but all the ones I found would cache the entire stream before selecting the sample.&amp;nbsp; This clearly isn't scalable as the input stream increases in size.&lt;/p&gt; &lt;p&gt;After a look around I found &lt;a href="http://www.cs.umd.edu/~samir/498/vitter.pdf"&gt;this blog article&lt;/a&gt; that describes how to implement Reservoir sampling without the need to keep all the items.&amp;nbsp; This then allowed me to write a Random Sample extension method to IEnumerable&amp;lt;T&amp;gt; to do what I needed.&lt;/p&gt; &lt;p&gt;public static IEnumerable&amp;lt;T&amp;gt; RandomSample&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; rows, int nSamples)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Random rnd = new Random();  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T[] sample = new T[nSamples];  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int nSamplesTaken = 0;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (T item in rows)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (nSamplesTaken &amp;lt; sample.Length)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sample[nSamplesTaken] = item;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // As the amount of samples increases the probability&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // of including a value gets less..due to the fact&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // that it has a greater chance of surviving if it gets&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // placed into the sample over earlier selections&lt;/p&gt; &lt;p&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (rnd.Next(nSamplesTaken) &amp;lt; nSamples) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sample[rnd.Next(nSamples)] = item;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nSamplesTaken++;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (nSamplesTaken &amp;gt;= nSamples)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return sample;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return sample.Take(nSamplesTaken);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-500183066891632065?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/500183066891632065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=500183066891632065' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/500183066891632065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/500183066891632065'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/10/random-sampling-extension-method.html' title='Random Sampling extension method'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6155161955149003774</id><published>2008-09-18T15:18:00.001+01:00</published><updated>2008-09-18T15:26:52.802+01:00</updated><title type='text'>Chrome support for Silverlight</title><content type='html'>&lt;p&gt;The Beta version of Chrome does not fully support silverlight the app appears to start but no screen updates happen unless you keep resizing the browser.&amp;nbsp;&amp;nbsp; Ive just switched to the Dev branch for Chrome and it appears now to be working .&lt;/p&gt; &lt;p&gt;You can switch via this&amp;nbsp; &lt;a href="http://dev.chromium.org/getting-involved/dev-channel"&gt;web site&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6155161955149003774?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6155161955149003774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6155161955149003774' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6155161955149003774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6155161955149003774'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/09/chrome-support-for-silverlight.html' title='Chrome support for Silverlight'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8888951058668489061</id><published>2008-09-17T07:01:00.001+01:00</published><updated>2008-09-17T07:01:48.840+01:00</updated><title type='text'>.NET 3.5 SP1 produces a re think of Optimised Lazy Singleton</title><content type='html'>&lt;p&gt;In the past I've used a version of double check locking in order to implement efficient lazy creation of a singleton in .NET.&amp;nbsp; This I've found to be the most performant implementation.&amp;nbsp; However I've noticed recently that things are changing, when I run the code on a 64 bit CLR I see no difference between a type that has the&amp;nbsp; before field init attribute present on or not.&amp;nbsp; Both get initialised lazily in release mode and extremely quickly.&amp;nbsp; The double check locking on 64 bit CLR is found to be less performant and therefore an unnecessary complication in the implementation.&lt;/p&gt; &lt;p&gt;In addition Ive recently installed .NET 3.5 SP1 and noticed now that there is a change in the 32 bit CLR for type initialisation.&amp;nbsp; Whilst I still get the normal behaviour of before field init, the lazy CLR based initialisation is now extremely quick, almost the same as non lazy initialisation of the type.&amp;nbsp; Again more importantly faster than my optimised double check locking implementation&lt;/p&gt; &lt;p&gt;My conclusion therefore is that moving forward, I'm comfortable in the fact that the very simple of singleton implementations is now acceptable even in cases where I'm aggressively requesting an instance of the singleton.&lt;/p&gt; &lt;p&gt;Below are two implementations of a singleton, the first using optimised locking the second using the CLR type initialisation to ensure lazy initialisation even in a multi threaded environment.&lt;/p&gt; &lt;p&gt;public class OptimisedLazyLogger&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static volatile OptimisedLazyLogger instance;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static object creationLock = new object();  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private OptimisedLazyLogger()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static OptimisedLazyLogger GetInstance()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (instance == null)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CreateInstance();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return instance;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void CreateInstance()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // only one thread at any one time&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // can be inside this block&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lock (creationLock)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (instance == null)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance = new OptimisedLazyLogger();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;p&gt;Implementation relying on CLR lazy initialisation&lt;/p&gt; &lt;p&gt;class LazyLogger&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static LazyLogger instance;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Type constructor&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static LazyLogger()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance = new LazyLogger();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ensure new can not be used outside the type&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // to create an instance&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private LazyLogger()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Lazy Logger Created");&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Public method to allow clients to get to the single &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // instance&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static LazyLogger GetInstance()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return instance;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void LogMsg(string msg)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("Logger: {0}" , msg );&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;p&gt;}&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8888951058668489061?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8888951058668489061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8888951058668489061' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8888951058668489061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8888951058668489061'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/09/net-35-sp1-produces-re-think-of.html' title='.NET 3.5 SP1 produces a re think of Optimised Lazy Singleton'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-4286074915758655660</id><published>2008-09-03T09:23:00.001+01:00</published><updated>2008-09-03T09:23:36.535+01:00</updated><title type='text'>Google Chrome, new browser or new desktop os ?</title><content type='html'>&lt;p&gt;Today I watched the google chrome demo, and I must say it looks awesome.&amp;nbsp; For me its not just a new browser its an attempt to create a desktop os to run web apps.&amp;nbsp; Even the language they use suggests that the overall aim&lt;/p&gt; &lt;p&gt;"We see chrome as more of a window manager"&lt;/p&gt; &lt;p&gt;Other highlights that elude to this are :-&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Each tabs run in separate process and sand boxed, even has its own task manager to kill tabs and plugins&lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;Compiled Java Script, allowing you to utilise java script more in your pages&lt;/p&gt; &lt;p&gt;Web Apps can be run without all the normal browser decoration, so they look like a normal desktop app, good uses of this are google calendar and gmail&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;And to top it all its open source....and works with any search provider...Other cool features Incognita windows allowing you to search the web with out recording the urls in the web history.&amp;nbsp; This proves to be important based on the fact that&amp;nbsp; it utilises browser history to optimise behaviour.&lt;/p&gt; &lt;p&gt;Google have created a desktop web platform that is optimised for searching and running web apps, perhaps in not so distant future all we will care about is having a machine that runs chrome and thats all we care about....Im for one going to be downloading chrome and start using it...&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://google.client.shareholder.com/Visitors/event/build2/MediaPresentation.cfm?MediaID=33101&amp;amp;Player=1"&gt;http://google.client.shareholder.com/Visitors/event/build2/MediaPresentation.cfm?MediaID=33101&amp;amp;Player=1&lt;/a&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-4286074915758655660?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/4286074915758655660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=4286074915758655660' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4286074915758655660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4286074915758655660'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/09/google-chrome-new-browser-or-new.html' title='Google Chrome, new browser or new desktop os ?'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-1728972287268267925</id><published>2008-08-19T08:47:00.001+01:00</published><updated>2008-08-19T08:47:20.464+01:00</updated><title type='text'>Developmentor Pfx Article</title><content type='html'>&lt;p&gt;I have written an article for Developmentor Developments magazine on the June 2008 CTP of Microsoft Parallel Extensions known as Pfx.&amp;nbsp; To read the article&amp;nbsp; &lt;a href="http://www.develop.com/us/email/developments/Microsoft_Pfx.doc"&gt;click here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-1728972287268267925?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/1728972287268267925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=1728972287268267925' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1728972287268267925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1728972287268267925'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/08/developmentor-pfx-article.html' title='Developmentor Pfx Article'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-2105980750543761665</id><published>2008-07-30T14:37:00.001+01:00</published><updated>2008-07-30T14:45:29.008+01:00</updated><title type='text'>Weak Observer</title><content type='html'>&lt;p&gt;During a recent teach of Code Smarter for Design Patterns in .NET&amp;nbsp; in which we teach the Observer pattern showing both traditional GOF implementation as well as a more appropriate .NET version using events.&amp;nbsp; One student after class told me he has never been keen on encouraging the use of event subscriptions as he was never confident that his developers would remember to unsubscribe from events when they no longer needed them.&amp;nbsp; This is in fact has been a common problem in .NET code that can often induce a memory leak.&lt;/p&gt; &lt;p&gt;The typical case that is often presented is one where a Windows Form subscribes to an event from a different object say some application object.&amp;nbsp; When the form subscribes to the event on the application object, the application object therefore has&amp;nbsp; a strong reference to the form so that it can deliver the events.&amp;nbsp; When the form is closed a failure to unsubscribe from the event means that there will still be a strong reference the form that will ultimately prevent it from being gc'd.&amp;nbsp; If this form has a large data table bound to a data grid this could have seriously impact on available memory during the applications life, as this data set will also not be gc'd&lt;/p&gt; &lt;p&gt;Clearly the right thing is for all programmers to remember to unsubscribe, but we know that often programmers forget and these leaks often go unnoticed until a customer screams.&amp;nbsp; An alternative would be for the application object not to hold&amp;nbsp; a reference and thus will not stop the window from being garbage collected, the obvious problem then is how can it deliver the event.&amp;nbsp; There is though a half way house through the use of a Weak Reference.&amp;nbsp; A Weak reference provides a means to reference an object without preventing it from being GC'd, but still allowing you to get to it whilst the GC'd hasn't decided to remove it.&lt;/p&gt; &lt;p&gt;As I said at the start we provide two implementations of the observer pattern one using interfaces, IObserver/IListener the other using .NET events.&amp;nbsp; Implementing a version of the observer pattern using the interface approach combined with Weak references is relatively trivial extension to the standard observer pattern.&amp;nbsp; The subject does not hold on to the observer/listener using a strong reference it is simply held as a weak reference. When the subject wishes to inform the observers of an event it walks through its list of weak refrerences turning each one into a strong reference for the duration of the notification.&amp;nbsp; If it fails to turn a weak reference into a strong reference it knows the observer has been gc'd.&lt;/p&gt; &lt;p&gt;When attempting to implement this behaviour using events things get a little bit more involved as the delegate chain holds the reference to the observer as a normal strong reference, that is something we can't change.&amp;nbsp; This is a shame since we would clearly love to have the choice to hold on to it as a weak reference, thus giving us a similar solution to Weak Observer.&amp;nbsp; In order to give an event style api we will need to be a bit more cunning, and also take a performance hit.&amp;nbsp; What I have done here is to continue to have the normal event subscribe/unsubscribe using a delegate, but then crack open the delegate to reveal the target instance and target method.&amp;nbsp; Once I have the target method and instance I wrap the instance up in a weak reference wrapped up by what I call a &lt;font face="Courier New"&gt;WeakEventHandle. &lt;/font&gt;After the construction of the handle it is placed into a handle list. When asked to fire the event each of the handles is visited in turn and the target method is invoked via reflection.&amp;nbsp; Invoking the method via reflection is not optimal in terms of performance and limits the possibilities of running the application with&amp;nbsp; reduced permissions .&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" size="4"&gt;private WeakEventMgr&amp;lt;SomeEventArgs&amp;gt; someEvent = new WeakEventMgr&amp;lt;SomeEventArgs&amp;gt;(); &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" size="4"&gt; public event EventHandler&amp;lt;SomeEventArgs&amp;gt; SomeEvent&lt;br&gt; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; add { someEvent.Add(value); }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; remove {someEvent.Remove(value); }&lt;br&gt; }&lt;/font&gt; &lt;p&gt;&lt;font face="Courier New" size="4"&gt;// .....&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" size="4"&gt;protected virtual void OnSomeEvent(SomeEventArgs someEventArgs)&lt;br&gt;{&lt;br&gt;&amp;nbsp; someEvent.Notify(this, someEventArgs);&lt;br&gt;}&lt;/font&gt; &lt;p&gt;Above is the code necessary to expose a WeakEvent, each event has its own instance of WeakEventMgr&amp;lt;T&amp;gt;.&amp;nbsp; The event subscribe/unscribe method is explicitly implemented to use WeakEventMgr as the backing store for the subscribers.&amp;nbsp; Finally to maintain the Microsoft pattern for event dispatch a virtual protected method exists to dispatch the event.&amp;nbsp; To make adding weak events easier I created a snippet.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Using one of the implementations of Weak Observer means there is now less need to worry about ensuring that all subscribers have unregistered, since event subscriptions will not keep an object alive.&lt;/p&gt; &lt;p&gt; You can download the code &lt;a href="http://www.beaconsoft.co.uk/Downloads/FormLeakage.zip"&gt;here&lt;/a&gt;.&amp;nbsp; The code demonstrates the classic problem of form leakage.&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2105980750543761665?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/2105980750543761665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=2105980750543761665' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2105980750543761665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2105980750543761665'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/07/weak-observer.html' title='Weak Observer'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6401581221791522014</id><published>2008-07-20T17:42:00.001+01:00</published><updated>2008-07-20T17:42:55.148+01:00</updated><title type='text'>Parallel Boids</title><content type='html'>&lt;p&gt;The last two weeks Ive found myself immersed in looking at the new Pfx CTP release.&amp;nbsp; I must say it has come on loads since the last drop in December.&amp;nbsp; Some of the issues I spoke about in a previous blog post have now been fixed, things like better algorithms for Parallel.For.&amp;nbsp; Perhaps some of the best addition is the set of concurrent data structures ( cds ).&amp;nbsp; &lt;/p&gt; &lt;p&gt;The main reason for digging into Pfx over the last two weeks was to write an article for the August edition of&amp;nbsp; &lt;a href="http://www.develop.com"&gt;Developmentor's&lt;/a&gt; "development's" monthly news letter, this article attempts to cover the highlights of the recent CTP, so after completing that part of it I had to find some fun use of Pfx, so I ported a developmentor favorite "Boids".&amp;nbsp; Anyone attending a Developmentor Esessntial .NET or Guerilla .NET will have probably encountered this app, but for those not in the know it is a simulation of flocking behaviour. &lt;/p&gt; &lt;p&gt;I took the initial code written by Jason Whittington and started tuning it for performance initially just using one core.&amp;nbsp; The main task was to reduce the number of loops, so instead of having two loops one after each other that iterate over the same set of data I simply combined them,&amp;nbsp; and the second optimisation was to replace foreach with a regular for loop.&amp;nbsp; After that I replaced the main outer for loop with Parallel.For , and viola a reasonable speed up...&lt;/p&gt; &lt;p&gt;I've run the code&amp;nbsp; on my dual core and on an eight way and in both cases observed a reasonable speed up...Not bad considering not a massive amount of effort.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/AndrewMarkClymer/SINrCDOXaiI/AAAAAAAAABs/YrOl3MDMXvQ/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="333" alt="image" src="http://lh5.ggpht.com/AndrewMarkClymer/SINrDR8QVlI/AAAAAAAAABw/bhZov0ERwRY/image_thumb%5B2%5D.png?imgmax=800" width="385" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;You can download the code from &lt;a href="http://www.beaconsoft.co.uk/download.html"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6401581221791522014?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6401581221791522014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6401581221791522014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6401581221791522014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6401581221791522014'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/07/parallel-boids.html' title='Parallel Boids'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/AndrewMarkClymer/SINrDR8QVlI/AAAAAAAAABw/bhZov0ERwRY/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-4747358065589770215</id><published>2008-06-06T10:08:00.001+01:00</published><updated>2008-06-06T10:08:22.878+01:00</updated><title type='text'>Software Architect Week Demos</title><content type='html'>&lt;p&gt;Had a lot of fun again at &lt;a href="http://www.software-architect.co.uk/venue/"&gt;Software Architect Week&lt;/a&gt;, the demos for the day of Design patterns can be downloaded from &lt;a href="http://www.software-architect.co.uk/slides/"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-4747358065589770215?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/4747358065589770215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=4747358065589770215' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4747358065589770215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4747358065589770215'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/06/software-architect-week-demos.html' title='Software Architect Week Demos'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-1473122822524702445</id><published>2008-05-18T22:53:00.001+01:00</published><updated>2008-05-18T22:53:45.860+01:00</updated><title type='text'>Classic Snake in Silverlight 2</title><content type='html'>&lt;p&gt;Inspired by Dave Wheeler's article in VSJ magazine, I decided it was time to write a simple game in Silverlight 2.&amp;nbsp; The game I chose was the classic game of Snake.&lt;/p&gt; &lt;p&gt;Whilst there is no doubt Silverlight 2 is a massive step closer to a .NET environment in the browser, there are still a few bits and pieces that trip you up.&amp;nbsp; Some of the collections data structures are not supported, LinkedList, Queue, Stack...there has been an underlying effort to keep the install of the platform as small as possible, so classes that have functionality that can be easily written using other classes have been tossed out. &lt;/p&gt; &lt;p&gt;As for WPF feature parity things have massively improved since we now have controls, not just simple shapes.&amp;nbsp; There is also now support for data binding and resources.&amp;nbsp; Things still trip you up though, transforms don't support data binding and results in less than obvious errors.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;You can play the game&amp;nbsp; &lt;a href="http://www.beaconsoft.co.uk/Games/Snake.html"&gt;here&lt;/a&gt; and download the source from &lt;a href="http://www.beaconsoft.co.uk/Downloads/ClassicSnake.zip"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-1473122822524702445?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/1473122822524702445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=1473122822524702445' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1473122822524702445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/1473122822524702445'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/05/classic-snake-in-silverlight-2.html' title='Classic Snake in Silverlight 2'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-4512078011449146120</id><published>2008-05-03T12:48:00.001+01:00</published><updated>2008-05-03T12:48:30.253+01:00</updated><title type='text'>CodeGen for base decorator</title><content type='html'>&lt;p&gt;One of the patterns in developmentor's &lt;a href="http://www.develop.com/us/training/course.aspx?id=663"&gt;"Code Smarter with design patterns in .NET course"&lt;/a&gt; is the decorator pattern.&amp;nbsp; The decorator pattern allows you to extend functionality at runtime, this works if the client is written in terms of an abstract type.&amp;nbsp; Using the class hierarchy below the client would be written in terms of the Component class.&amp;nbsp; The code wishing to call the client has been given an instance of ConcreteComponent, but it wants to extend the functionality of that object, in order to do this it must create another object that looks like what the client is expecting.&amp;nbsp; This is where the decorator comes in, the component decorator class below is compatible with the client since it also derives from Component.&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/AndrewMarkClymer/SBwO0bT6qAI/AAAAAAAAABY/kYCCkf4FPdY/s1600-h/image%5B3%5D.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="241" alt="image" src="http://lh4.ggpht.com/AndrewMarkClymer/SBxRDbT6qBI/AAAAAAAAABk/lElYAG_A4gU/image_thumb%5B1%5D.png?imgmax=800" width="260" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The componentDecorator class is a null decorator it simply supports the ability to wrap an object of type Component, and when any of its methods are invoked the call is simply passed&amp;nbsp; on to the wrapped object. Since it has no real functionality it is also declared abstract.&amp;nbsp; Each of the types DecoratorOne and DecoratorTwo overrride only the methods they wish to extend, the methods they do not wish to extend are simply handled by the base class ComponentDecorator and forwarded to the wrapped object.&amp;nbsp; Before calling the client a decorator object is created, and is given the object it is to decorate, in this case something of type component.&amp;nbsp; It is now this decorated object that is passed into the client. &lt;/p&gt; &lt;p&gt;The building of the ComponentDecorator class can become very tedious if the Component class has lots of methods that need to be implemented.&amp;nbsp; This week I finally got around to writing some code that via reflection and the CodeDom classes that will generate the base decorator class, saving a reasonable amount of time and effort.&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.beaconsoft.co.uk/download.html"&gt;The code can be found&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-4512078011449146120?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/4512078011449146120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=4512078011449146120' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4512078011449146120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/4512078011449146120'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/05/codegen-for-base-decorator.html' title='CodeGen for base decorator'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/AndrewMarkClymer/SBxRDbT6qBI/AAAAAAAAABk/lElYAG_A4gU/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-2687583124715540692</id><published>2008-04-03T09:44:00.001+01:00</published><updated>2008-04-03T09:44:46.658+01:00</updated><title type='text'>Web Guidelines from the street</title><content type='html'>&lt;p&gt;Dom found this link, &lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:fb8bc987-c503-40fb-9b42-389b8e8dcb56" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;div&gt;&lt;object width="425" height="350"&gt;&lt;param name="movie" value="http://www.youtube.com/v/a0qMe7Z3EYg&amp;amp;hl=en"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/a0qMe7Z3EYg&amp;amp;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="350"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2687583124715540692?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/2687583124715540692/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=2687583124715540692' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2687583124715540692'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2687583124715540692'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/04/web-guidelines-from-street.html' title='Web Guidelines from the street'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-2981752427918698429</id><published>2008-04-02T18:01:00.001+01:00</published><updated>2008-04-02T18:01:59.165+01:00</updated><title type='text'>Generic Sum</title><content type='html'>&lt;p&gt;Its been a while since I blogged about trying to re-implement C++ STL using .NET generics.&amp;nbsp; Last night I was skimming through an excellent book on Linq "Linq in Action" published by Manning, and whilst reading the section on how Expression trees work in C# v3.0 it occured to me that I could potentially use them for creating a generic Sum method.&lt;/p&gt; &lt;p&gt;First a quick look at C# v3.0 expressions,&amp;nbsp; the lambda expression here is not being turned into a method as would be the norm for anonymous methods but it is turned into an AST.&amp;nbsp; Abstract Syntax Tree used to describe the function of the lambda expression.&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="708" bgcolor="#c8c8c8" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="706"&gt; &lt;p&gt;&lt;font face="Courier New"&gt;Expression&amp;lt;Func&amp;lt;int, int, int&amp;gt;&amp;gt; addExpr = (lhs, rhs) =&amp;gt; lhs + rhs;&lt;/font&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;Func&amp;lt;int, int, int&amp;gt; addMethod = addExpr.Compile(); &lt;/font&gt; &lt;p&gt;&lt;font face="Courier New"&gt;Console.WriteLine(addMethod(5, 5));&lt;/font&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;In this case that produces a root node to the expression tree that is a Lambda node, that then contains a single Add node, which is a binary operator thus containing two further nodes for the left hand side and right hand side of the add operation.&lt;/p&gt; &lt;p&gt;Reflector spits out the following code&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2" width="600" bgcolor="#c8c8c8" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="600"&gt;&lt;pre&gt;private static &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Void"&gt;void&lt;/a&gt; &lt;b&gt;&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Expressions:1.0.0.0/Expressions.Program/Main(String%5b%5d)"&gt;Main&lt;/a&gt;&lt;/b&gt;(&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.String"&gt;string&lt;/a&gt;[] args)&lt;br /&gt;{&lt;br /&gt;    &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.ParameterExpression"&gt;ParameterExpression&lt;/a&gt; &lt;b&gt;CS$0$0000&lt;/b&gt;;&lt;br /&gt;    &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.ParameterExpression"&gt;ParameterExpression&lt;/a&gt; &lt;b&gt;CS$0$0001&lt;/b&gt;;&lt;br /&gt;    &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Console"&gt;Console&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Console/WriteLine(Int32)"&gt;WriteLine&lt;/a&gt;(&lt;/pre&gt;&lt;pre&gt;      &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.Expression"&gt;Expression&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.Expression/Lambda&amp;lt;&amp;gt;(System.Linq.Expressions.Expression,System.Linq.Expressions.ParameterExpression%5b%5d):System.Linq.Expressions.Expression&amp;lt;&amp;lt;!!0&amp;gt;&amp;gt;"&gt;Lambda&lt;/a&gt;&amp;lt;&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Func&amp;lt;,,&amp;gt;"&gt;Func&lt;/a&gt;&amp;lt;&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Int32"&gt;int&lt;/a&gt;, &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Int32"&gt;int&lt;/a&gt;, &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Int32"&gt;int&lt;/a&gt;&amp;gt;&amp;gt;(&lt;/pre&gt;&lt;pre&gt;        &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.Expression"&gt;Expression&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.Expression/Add(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):System.Linq.Expressions.BinaryExpression"&gt;Add&lt;/a&gt;(&lt;/pre&gt;&lt;pre&gt;           &lt;a&gt;CS$0$0000&lt;/a&gt; = &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.Expression"&gt;Expression&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.Expression/Parameter(System.Type,String):System.Linq.Expressions.ParameterExpression"&gt;Parameter&lt;/a&gt;(typeof(&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Int32"&gt;int&lt;/a&gt;), "lhs"), &lt;/pre&gt;&lt;pre&gt;           &lt;a&gt;CS$0$0001&lt;/a&gt; = &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.Expression"&gt;Expression&lt;/a&gt;.&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.Expression/Parameter(System.Type,String):System.Linq.Expressions.ParameterExpression"&gt;Parameter&lt;/a&gt;(typeof(&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Int32"&gt;int&lt;/a&gt;), "rhs")),&lt;/pre&gt;&lt;pre&gt;       new &lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.ParameterExpression"&gt;ParameterExpression&lt;/a&gt;[] { &lt;a&gt;CS$0$0000&lt;/a&gt;, &lt;a&gt;CS$0$0001&lt;/a&gt; }&lt;/pre&gt;&lt;pre&gt;     ).&lt;a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Core:3.5.0.0:b77a5c561934e089/System.Linq.Expressions.Expression&amp;lt;&amp;gt;/Compile():&amp;lt;!0&amp;gt;"&gt;Compile&lt;/a&gt;()(5, 5));&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;This got me thinking could I build an expression using generic arguments, the code as spit out by reflector certainly looks like its possible.&amp;nbsp; My first crack was as follows&lt;/p&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="681" bgcolor="#c8c8c8" border="1"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td valign="top" width="679"&gt;&lt;br /&gt;&lt;p&gt;public static T Sum&amp;lt;T&amp;gt;(T[] vals)&lt;br&gt;{ &lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression&amp;lt;Func&amp;lt;T, T, T&amp;gt;&amp;gt; addExpr = (lhs, rhs) =&amp;gt; lhs + rhs; &lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T total = default(T); &lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;T, T, T&amp;gt; addMethod = addExpr.Compile()&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (T val in vals)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; total = addMethod(total, val);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return total;&lt;br&gt;}&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;Unfortunately this failed, with the typical "Operator + cannot be applied to operands of type T and T" error that has been the reason why you can't easily write generic Sum in .NET.&amp;nbsp; However not put off I built the expression tree by hand&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="798" bgcolor="#c8c8c8" border="1"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td valign="top" width="796"&gt;&lt;br /&gt;&lt;p&gt;private static Func&amp;lt;T, T, T&amp;gt; CreateAdd&amp;lt;T&amp;gt;()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ParameterExpression lhs = Expression.Parameter(typeof(T), "lhs");&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ParameterExpression rhs = Expression.Parameter(typeof(T), "rhs"); &lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression&amp;lt;Func&amp;lt;T, T, T&amp;gt;&amp;gt; addExpr = Expression&amp;lt;Func&amp;lt;T, T, T&amp;gt;&amp;gt;.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Lambda&amp;lt;Func&amp;lt;T, T, T&amp;gt;&amp;gt;(&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Expression.Add(lhs, rhs), &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new ParameterExpression[] { lhs, rhs });&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;T, T, T&amp;gt; addMethod = addExpr.Compile(); &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return addMethod;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;The method above now returns a delegate instance that adds two values both of type T, and returns a value as type T.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Generic Sum can now be rewritten as follows&lt;/p&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="793" bgcolor="#c8c8c8" border="1"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td valign="top" width="791"&gt;&lt;br /&gt;&lt;p&gt;public static T Sum&amp;lt;T&amp;gt;(T[] vals)&lt;br&gt;{ &lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T total = default(T); &lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;T, T, T&amp;gt; addMethod = CreateAdd&amp;lt;T&amp;gt;(); &lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (T val in vals)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; total = addMethod(total, val);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return total;&lt;br&gt;}&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This now works for arrays for ints, doubles etc.&amp;nbsp; It will not work for types not supported by the Add Expression, so only works for simple numeric types, but it is certainly a lot simpler than the approach I took a year or so ago although not as flexible.&amp;nbsp; Its a shame that the C# compiler expression tree builder won't accept generic arguments since it is possible to represent a expression tree this way, as this would result in a lot easier way to generate such code.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2981752427918698429?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/2981752427918698429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=2981752427918698429' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2981752427918698429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2981752427918698429'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/04/generic-sum.html' title='Generic Sum'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6522505450127775908</id><published>2008-04-02T17:26:00.001+01:00</published><updated>2008-04-02T17:26:41.736+01:00</updated><title type='text'>Looking for a C# Design Patterns book</title><content type='html'>&lt;p&gt;I co-author&amp;nbsp; developmentor's Code smarter with Design Patterns in .NET course with Kevin Jones, and ever since the creation of the course I've been on the look out for a good book to recommend to students.&amp;nbsp; The one I currently recommend is the excellent Head First Design Patterns, although the only rub is its in Java, but in terms of teaching patterns its awesome.&lt;/p&gt; &lt;p&gt;I recently decided to order the latest Design Patterns for C# v3.0 from OReilly written by Judith Bishop, and see if I could recommend that text.&amp;nbsp; Yesterday it arrived, and I skimmed though it looking at the&amp;nbsp; various classic patterns Observer, Template..and my was I shocked...the implementation of some of the patterns is just plane weird, and some of the patterns basic structure is plainly wrong as defined by GOF.&lt;/p&gt; &lt;p&gt;I've not been through the entire catalogue of patterns, but here are some examples.&lt;/p&gt; &lt;p&gt;Template pattern is shown to use composition as opposed to inheritance to bind the template method to the template steps, this is plainly wrong and the implementation is therefore a strategy pattern.&amp;nbsp; As for the strategy pattern examples none of them really effectively show the use of&amp;nbsp; supplying runtime specific behaviour to&amp;nbsp; a subsystem or algorithm.&amp;nbsp; &lt;/p&gt; &lt;p&gt;The observer pattern uses a weird combination of delegates and IObserver interface, its either one or the other, and for .NET is almost certainly pure delegate/event.&amp;nbsp; The is no obvious reason why she has used both interface and delegates/events&lt;/p&gt; &lt;p&gt;The Abstract Factory pattern makes use of a generic interface for the Abstract Factory, but no where in the interface is the generic argument references, and thus is seemingly redundant.&lt;/p&gt; &lt;p&gt;The command pattern mixes the implementation of the invoker with the implementation of the command.&amp;nbsp; &lt;/p&gt; &lt;p&gt;In conclusion I'm not convinced the author either knows the patterns as defined by the GOF, nor is highly proficient in C# v3.0.&amp;nbsp; So my quest continues to find a good C# patterns book I can recommend for class..&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6522505450127775908?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6522505450127775908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6522505450127775908' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6522505450127775908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6522505450127775908'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/04/looking-for-c-design-patterns-book.html' title='Looking for a C# Design Patterns book'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-9095201598321413903</id><published>2008-02-13T21:44:00.001Z</published><updated>2008-02-13T21:44:19.878Z</updated><title type='text'>True Generic Singleton</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;Last weekend I was teaching &lt;a href='http://www.develop.com/uk/training/course.aspx?id=663'&gt;Code Smarter with Design Patterns in .NET&lt;/a&gt;, yep that's right a weekend...The guys at Intelliflo decided they didn't have time during the regular week for training that wanted me to pack a 4 day course into 3 days over the weekend so we worked from 9 until 19:00...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Whilst teaching them the Singleton pattern they bought out a version they were using built on Generics. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;AlmostSingleton&lt;/span&gt;&amp;lt;T&amp;gt; &lt;span style='color:blue'&gt;where&lt;/span&gt; T:&lt;span style='color:blue'&gt;new&lt;/span&gt;()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;    {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt; T instance;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt; initLock = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt; T GetInstance()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (instance == &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                CreateInstance();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;            }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;return&lt;/span&gt; instance;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; CreateInstance()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;lock&lt;/span&gt; (initLock)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (instance == &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                    instance = &lt;span style='color:blue'&gt;new&lt;/span&gt; T();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;            }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;    }&lt;/span&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;AlmostSingleton&lt;/span&gt;&amp;lt;&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt; Highlander()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(&lt;span style='color:#a31515'&gt;"There can be only one..."&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;}&lt;/span&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; Main(&lt;span style='color:blue'&gt;string&lt;/span&gt;[] args)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt; highlander = &lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt;.GetInstance();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt; highlander2 = &lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt;.GetInstance();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Debug&lt;/span&gt;.Assert(&lt;span style='color:blue'&gt;object&lt;/span&gt;.ReferenceEquals(highlander, highlander2));&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;A bit of a google around and it appears a few people are advocating similar solutions.  On the surface all looks well, but to be really true to the singleton pattern the type which is the singleton should only ever have a single instance.  This implementation requires T to have a public constructor, so that whilst it is certainly possible to always get back to a common instance via the GetInstance method, what is lacking and what the singleton pattern strictly requires is the enforcing of only a single instance of the type.  Since the fact that the type has a public constructor means that another client could easily create an instance as opposed to calling GetInstance().&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; Main(&lt;span style='color:blue'&gt;string&lt;/span&gt;[] args)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt; highlander = &lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt;.GetInstance();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt; highlander2 = &lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt;.GetInstance();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Debug&lt;/span&gt;.Assert(&lt;span style='color:blue'&gt;object&lt;/span&gt;.ReferenceEquals(highlander, highlander2));&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;    // This will create a second instance of Highlander..&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;    // not what we want support&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt; highlander3 = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt; }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;In fact supporting the true singleton behaviour isn't too hard, it simply requires the use of a bit of reflection to create the object instance rather than rely on the typical language new construct.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;Singleton&lt;/span&gt;&amp;lt;&lt;span style='color:#2b91af'&gt;Highlander&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt; Highlander()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(&lt;span style='color:#a31515'&gt;"There can be only one..."&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;}&lt;/span&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Singleton&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;    {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt; T instance;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt; initLock = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt; T GetInstance()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (instance == &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                CreateInstance();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;            }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;return&lt;/span&gt; instance;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; CreateInstance()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;lock&lt;/span&gt; (initLock)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (instance == &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Type&lt;/span&gt; t = &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(T);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:green'&gt;// Ensure there are no public constructors...&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;ConstructorInfo&lt;/span&gt;[] ctors = t.GetConstructors();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (ctors.Length &amp;gt; 0)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                    {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;throw&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;InvalidOperationException&lt;/span&gt;(&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style='margin-left: 108pt'&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;span style='color:#2b91af'&gt;String&lt;/span&gt;.Format(&lt;span style='color:#a31515'&gt;"{0} has at least one accesible ctor making it impossible to enforce singleton behaviour"&lt;/span&gt;,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                            t.Name));&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                    }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;&lt;br /&gt;					&lt;span style='color:green'&gt;// Create an instance via the private constructor&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                    instance = (T)&lt;span style='color:#2b91af'&gt;Activator&lt;/span&gt;.CreateInstance(t, &lt;span style='color:blue'&gt;true&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;            }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Verdana; font-size:16pt'&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Now any attempt to create the instance outside the Highlander class using the new keyword would produce a compiler error, thus enforcing the true singleton pattern.  I've also added a guard to make sure that when you use the Generic wrapper it ensures that you do not have a public constructor which would ultimately allow a client to by bass the singleton functionality.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-9095201598321413903?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/9095201598321413903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=9095201598321413903' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/9095201598321413903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/9095201598321413903'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/02/true-generic-singleton.html' title='True Generic Singleton'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6655507115426183639</id><published>2008-01-31T17:54:00.001Z</published><updated>2008-01-31T17:54:43.172Z</updated><title type='text'>Safe Event snippet</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;This week Im teaching the course I co-wrote with Kevin Jones "Code Smarter with Design Patterns in .NET", as part of the course we introduce the observer pattern and whilst the first part of the deck deals with the basic principles we soon move on to the prefered way of doing it in .NET using delegates/events.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;When using events in a multi threaded environment care needs to be taken as whilst register/unregister of the events is thread safe, care needs to be taken when raising the event.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Typically we see code like this&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Public class Subject&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;public event  EventHandler&amp;lt;EventArgs&amp;gt; Alert;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;    // ...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;    protected virtual void OnAlert(EventArgs args)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        If ( Alert != null )&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;            Alert( this , args )&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        }&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    }&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Here a check is being made to make sure the delegate chain has at least one instance, however whilst this works in a single threaded environment in a multithreaded environment there is a race condition between the if and the firing of the event.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;To get around this problem, one way is to take a local copy of the delegate reference, and compare that.  Since register/unregister events build new lists thus making the register/unregister thread safe.  However there is a simpler approach and that is to use the null pattern&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;public event  EventHandler&amp;lt;EventArgs&amp;gt; Alert = delegate { };&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;This will simple create a delegate instance at the head of the delegate chain which is never removed.  Thus its then safe to simply do&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;    Alert( this , args )&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Without checking for null, since that can't happen.  Ok there is an overhead, but it certainly makes the logic simpler and less prone to occasional hard to find race conditions.  Remembering to do this could be  a pain so I wrote a simple snippet to do it...So now I simply type safeevent TAB TAB and I always get an event with a null handler...another great use of anonymous methods...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6655507115426183639?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6655507115426183639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6655507115426183639' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6655507115426183639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6655507115426183639'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/01/safe-event-snippet.html' title='Safe Event snippet'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-251065901575855317</id><published>2008-01-25T11:00:00.001Z</published><updated>2008-01-25T11:00:57.394Z</updated><title type='text'>Not so much killer app, but killer content</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;It used to be the case that a computer/os would succeed if it had the killer app, the app everyone needed.  The spreadsheet was one of the first of that kind, now in the new media streaming age perhaps its killer content that will help to push the adoption of new  technology.  A student told me last week that Microsoft has done a deal so that MSN is the official home of the 2008 Olympic, the site will provide hours and hours of online coverage, bought to you by Silverlight.  Could there be any better vehicle to get Silverlight plugin onto every home/office pc..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;a href='http://blogs.msdn.com/somasegar/archive/2008/01/07/2008-olympics-brought-to-you-by-silverlight.aspx'&gt;Read More&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-251065901575855317?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/251065901575855317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=251065901575855317' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/251065901575855317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/251065901575855317'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/01/not-so-much-killer-app-but-killer.html' title='Not so much killer app, but killer content'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-5585950397820232205</id><published>2008-01-21T16:54:00.001Z</published><updated>2008-01-21T16:54:01.619Z</updated><title type='text'>The potential danger of too much access to too much data</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;The UK government is set to build a series of large scale databases containing children's data.  The charity Action on Rights for Children has put together a three part video detailing some of their concerns to this scheme.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;a href='http://www.youtube.com/watch?v=LRQr2VrtX-0'&gt;http://www.youtube.com/watch?v=LRQr2VrtX-0&lt;/a&gt;&lt;br /&gt;				&lt;br/&gt; &lt;br/&gt;&lt;a href='http://www.youtube.com/watch?v=KH-1IumXZbI'&gt;http://www.youtube.com/watch?v=KH-1IumXZbI&lt;/a&gt;&lt;br /&gt;				&lt;br/&gt;&lt;br/&gt;&lt;a href='http://www.youtube.com/watch?v=IyXCSg-lRkA'&gt;http://www.youtube.com/watch?v=IyXCSg-lRkA&lt;/a&gt;&lt;br /&gt;				&lt;br/&gt;&lt;br/&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-5585950397820232205?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/5585950397820232205/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=5585950397820232205' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5585950397820232205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5585950397820232205'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/01/potential-danger-of-too-much-access-to.html' title='The potential danger of too much access to too much data'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-6367099636536934518</id><published>2008-01-18T17:27:00.001Z</published><updated>2008-01-18T17:27:35.285Z</updated><title type='text'>Ensure local transaction snippet</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;Whilst teaching developmentors enet 3 class this week I had an idea for a new snippet.  It came to me whilst teaching the deck on System.Transactions, I was in the middle of demonstrating to them how you need to be really careful not to cause a transaction to be promoted to the DTC ( See &lt;a href='http://andyclymer.blogspot.com/2007/01/transactionscope-and-dataadapters.html'&gt;Previous Blog Article&lt;/a&gt; ).  Two strategies I suggest are&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;ol&gt;&lt;li&gt;Stop the DTC, net stop MSDTC&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add an Debug.Assert statement inside your TransactionScope block to ensure the current transaction is not a distributed transaction, by checking that the DistributedIdentifier is an empty GUID.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;The first option is reasonable if you never need the DTC, but if you do have bits of code that does need the DTC its clearly not an option.  The second approach is a bit tedious ut if you use a snippet, then its not all that bad.  Below is the snippet code..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;CodeSnippet&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Format&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;1.0.0&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;xmlns&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet&lt;/span&gt;"&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;  &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Header&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Title&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;/span&gt;Local Transaction&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Title&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Author&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;/span&gt;Andrew Clymer&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Author&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Shortcut&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;/span&gt;lscope&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Shortcut&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Description&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;/span&gt;Creates a transaction scope and ensures at the end of the block that the transaction is only a local transaction &lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Description&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;SnippetTypes&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;      &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;SnippetType&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;/span&gt;SurroundsWith&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;SnippetType&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;      &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;SnippetType&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;/span&gt;Expansion&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;SnippetType&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;SnippetTypes&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;  &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Header&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;  &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Snippet&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Declarations&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;      &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Literal&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;ID&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;/span&gt;scope&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;ID&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Default&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;/span&gt;scope&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Default&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;      &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Literal&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Declarations&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Code&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Language&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;CSharp&lt;/span&gt;"&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:blue; font-family:Courier New; font-size:10pt'&gt;      &amp;lt;![CDATA[&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:gray; font-family:Courier New; font-size:10pt'&gt;       using (TransactionScope $scope$ = new TransactionScope())&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:gray; font-family:Courier New; font-size:10pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='color:gray; font-family:Courier New; font-size:10pt'&gt;                $selected$&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:gray; font-family:Courier New; font-size:10pt'&gt;                $end$&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='color:gray; font-family:Courier New; font-size:10pt'&gt;                Debug.Assert(Transaction.Current.TransactionInformation.DistributedIdentifier == Guid.Empty,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:gray; font-family:Courier New; font-size:10pt'&gt;                    "Unexpected!! Transaction is now distributed");&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:gray; font-family:Courier New; font-size:10pt'&gt;            }      &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:gray'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:blue'&gt;]]&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Code&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;  &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Snippet&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;CodeSnippet&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-6367099636536934518?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/6367099636536934518/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=6367099636536934518' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6367099636536934518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/6367099636536934518'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/01/ensure-local-transaction-snippet.html' title='Ensure local transaction snippet'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-2980279523675295764</id><published>2008-01-13T18:25:00.001Z</published><updated>2008-01-13T18:25:41.567Z</updated><title type='text'>Pfx, Parallel Extensions take advantage of multiple cores, but be careful... </title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;Microsoft has now made available a parallel library for .NET, its still in early stages with its aim is to make it easier to write applications to take advantage of multiple cores.  Pfx has really two layers one which offers a relatively high level of abstraction, providing a Parallel.For, Parallel.Do and parallel LINQ and a lower level layer allowing programmers to schedule individual Tasks.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This has been a long time coming, .NET support for concurrency is pretty primitive even in .NET 3.0.  Simple things like kick of N tasks and wait for them all to complete requires a reasonable amount of code, but on the surface Pfx looks to assist here.  I spent a couple of days over xmas looking at it and understanding how it works.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;So first task was to find some code I wanted to parallelise I  frequently use a piece of logic I stole from the book "How long is a piece of string" that uses many iterations to work out the value of PI as a good async demo,  so I thought I would have a go at parallelising this piece of code.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;const&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;int&lt;/span&gt; N_ITERATIONS = 1000000000;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; CalcPi()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; pi = 1.0;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; multiply = -1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;for&lt;/span&gt; (&lt;span style='color:blue'&gt;int&lt;/span&gt; nIteration = 3; nIteration &amp;lt; N_ITERATIONS; nIteration += 2)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                pi += multiply * (1.0 / (&lt;span style='color:blue'&gt;double&lt;/span&gt;)nIteration);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                multiply *= -1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;return&lt;/span&gt; pi * 4.0;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;Looking at the algorithm it doesn't look that complicated all I need to do is to make each core do a different part of the for statement and then combine the results of each core and multiple by 4.0.  In fact Ive done this using the basic BeginInvoke functionality before so I know it scales...&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;So I first opted for the high level approach offered by Pfx called Parallel.For.  Which it states allows me to spread loop iterations across multiple cores.  In other words nIteration in my case could be 3 on one core and 5 on another at the same time.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; CalcPiSimpleParallel()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; pi = 1.0;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;           &lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt; sync = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:green'&gt;//for (int nIteration = 3; nIteration &amp;lt; 1000000000; nIteration += 2)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Parallel&lt;/span&gt;.For&amp;lt;&lt;span style='color:blue'&gt;double&lt;/span&gt;&amp;gt;(0, N_ITERATIONS / 2 , 1, () =&amp;gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt; 0; }, (nIteration, localPi) =&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; multiply = 1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:green'&gt;// 3 5 7 9 11 &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (nIteration % 2 == 0 )&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                    multiply = -1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                localPi.ThreadLocalState += multiply * (1.0 / (3.0 + (&lt;span style='color:blue'&gt;double&lt;/span&gt;)nIteration* 2.0 ));&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            },&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            (localPi) =&amp;gt; { &lt;span style='color:blue'&gt;lock&lt;/span&gt; (sync) { pi += localPi; } });&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;return&lt;/span&gt; pi * 4.0;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;This unfortunately this did not achieve the results I had hoped for...it in fact took twice as long...Bizare...Ok so not suprising since it is using delegates.    Using reflector you see that Parallel.For is using the underlying Task class provided by Pfx.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;A Task is a piece of work that you give to a task manager and it queue's for an available thread.  Now the first thing to mention is that tasks do not run on thread pool threads, a task manager has its own pool of threads which it controls depending on the number of available cores and if the tasks running are currently blocked. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:#2b91af'&gt;Task&lt;/span&gt; task = &lt;span style='color:#2b91af'&gt;Task&lt;/span&gt;.Create((o) =&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            Console.WriteLine("Task Running..");&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        } );&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;task.Wait();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;The code above will create a new task, and it will be run on one of the default Task Managers threads, and the main thread will wait for its completion. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Parallel.For, uses a special variant of Task called a replicating task, which means when you create this task the task manager will effectively not create a single instance of the task but in fact as many instances as there are cores.  Each of these task clones are then expected to work in harmony to achieve the overall task.  A typical implementation might therefore have an outerloop looking for a new piece of work to do in the overall task, when no more work it simply ends the task.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In the case of a Parallel.For you could expect the outerloop to simply perform an Interlocked.Increment on the loop counter until the required value is reached, and then inside the loop to simply invoke the required piece of work, and here lies the problem in my example in that the piece of work that is executing inside the for loop is extremely trivial and doesn't take that many cycles, and so the overhead of invoking a delegate for each iteration is having a large impact on the overall performance. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;So first word of warning when using Pfx, you need to make sure that the piece of work inside a given task is of a reasonable size in order for it to actually scale.  Ok so it's not as trivial as it first looks to parallelise the calc Pi method.  Not put off I refactored the code to make the algorithm have an inner loop, thus increasing the amount of work for each parallel for iteration.  To start with I simple broke it down into ten blocks, thinking each block would now be a reasonable amount of work and we would be only paying the overhead of a function call 10 times, as opposed to N_ITERATIONS/2&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; CalcPiDualLoop()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; pi = 1.0;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt; sync = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;int&lt;/span&gt; stride = N_ITERATIONS / 2 / 10;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:green'&gt;//for (int nIteration = 3; nIteration &amp;lt; 1000000000; nIteration += 2)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Parallel&lt;/span&gt;.For&amp;lt;&lt;span style='color:blue'&gt;double&lt;/span&gt;&amp;gt;(0, N_ITERATIONS / 2, stride, () =&amp;gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt; 0; }, (nIteration, localPi) =&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; multiply = 1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:green'&gt;// 3 5 7 9 11 &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (nIteration % 2 == 0)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                    multiply = -1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; piVal = 0;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;for&lt;/span&gt; (&lt;span style='color:blue'&gt;int&lt;/span&gt; val = nIteration; val &amp;lt; nIteration + stride ; val++)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                    piVal += multiply * (1.0 / (3.0 + (&lt;span style='color:blue'&gt;double&lt;/span&gt;)val * 2.0));&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                    multiply *= -1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                localPi.ThreadLocalState += piVal;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            },&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            (localPi) =&amp;gt; { &lt;span style='color:blue'&gt;lock&lt;/span&gt; (sync) { pi += localPi; } });&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;return&lt;/span&gt; pi * 4.0;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;But only partial luck, I got a less than 10% speed up...not what I was expecting.  So I had another look at the implmentation of Parallel.For to understand why, and digging into it you realise that each of the task created by parallel for, doesn't just take the next value in the loop and work on that, but takes the next eight values.  So what this means is that in my case I have an 2 core CPU, the first task to run takes the first 8 iterations of the loop to work on, and the second task gets just 2.  The second task completes its work, and since there is no more ends, leaving the first task to complete its remaining 6 all running on one core, leaving my other core cold.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;To make sure I wasn't seeing things I made the number of itterations of Parallel a factor of 8 * number of cores, and hey presto it took just over half the time.  &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;I can see that taking chunks of work at a time reduces contention for work allocation, but Im struggling to see why this would be neccessary since this contention will not be that great especically when in order to make Parallel.For to work efficiently each iteration needs to be of a reasonable size.  I really hope they address this issue when they finally release the library, since having to know how many cores you are running on and magic number 8 just seems rather odd and goes against what I believe they were trying to achieve.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;I also implemented the method using the low level parallel task library and that scales beautifully too..&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; ParallelCalcPi()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt; sync = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;int&lt;/span&gt; nIteration = 3;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; pi = 1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;int&lt;/span&gt; stride = N_ITERATIONS / 4;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;                             &lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Task&lt;/span&gt; task = &lt;span style='color:#2b91af'&gt;Task&lt;/span&gt;.Create((o) =&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Console&lt;/span&gt;.WriteLine(&lt;span style='color:#a31515'&gt;"Running..{0}"&lt;/span&gt;, &lt;span style='color:#2b91af'&gt;Thread&lt;/span&gt;.CurrentThread.ManagedThreadId);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; localPi =0.0;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;double&lt;/span&gt; multiply = -1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;long&lt;/span&gt; end;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;while&lt;/span&gt; ((end = &lt;span style='color:#2b91af'&gt;Interlocked&lt;/span&gt;.Add(&lt;span style='color:blue'&gt;ref&lt;/span&gt; nIteration, stride)) &amp;lt;= N_ITERATIONS + 3)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:green'&gt;//Console.WriteLine("Next Chunk {0} from {1} to {2}", Thread.CurrentThread.ManagedThreadId,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:green'&gt;//    end - stride, end);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;for&lt;/span&gt; (&lt;span style='color:blue'&gt;int&lt;/span&gt; val = (&lt;span style='color:blue'&gt;int&lt;/span&gt;) (end - stride); val &amp;lt; end; val += 2)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                    {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                        localPi += multiply * (1.0 / (&lt;span style='color:blue'&gt;double&lt;/span&gt;)val);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                        multiply *= -1;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                    }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;lock&lt;/span&gt; (sync) { pi += localPi; }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            }, &lt;span style='color:#2b91af'&gt;TaskCreationOptions&lt;/span&gt;.SelfReplicating);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            task.Wait();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;return&lt;/span&gt; pi * 4.0;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;First impressions is that the Task Library seems ok, but the Parallel.For seems ill thought out.  I have also done some experiments with Parallel.Do which allows me to kick of multiple tasks, by supplying a series of Action delegates as parameters.  Parallel.Do then blocks waiting for them to complete.  Unfortuantly no timeout parameter is present whih means it waits forever, so if an action goes into a rogue state and never completes, your thread that invoked Parallel.Do will hang, not desirable....So my second request is that they add a timeout parameter.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;				&lt;/span&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-2980279523675295764?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/2980279523675295764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=2980279523675295764' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2980279523675295764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/2980279523675295764'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2008/01/pfx-parallel-extensions-take-advantage.html' title='Pfx, Parallel Extensions take advantage of multiple cores, but be careful... '/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-9030070143205497657</id><published>2007-10-22T11:49:00.001+01:00</published><updated>2007-10-22T11:49:22.512+01:00</updated><title type='text'>Mobile Bingo</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;Just couldn't help myself in writing a bingo caller for my Mobile phone the other week, you see it was my daughter's birthday and she wanted bingo at the party and my wife had decided the low tech approach of pulling numbers out of a bag was the way to go...I wasn't having it "I could write a .NET App for my phone in 10 minutes to do that" I said.  Kind of brave since it was my first mobile phone app, I paid £300 for this phone so it just has to do more than just make calls...You know what a bit more than 10 minutes say 30 and I had it working...It just goes to show easy things have become these days....Im thinking of porting wack a mole now...although I'm not sure my touch sensitive screen will last...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;You can download the app from &lt;a href='http://www.beaconsoft.co.uk/download.html'&gt;here&lt;/a&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-9030070143205497657?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/9030070143205497657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=9030070143205497657' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/9030070143205497657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/9030070143205497657'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/10/mobile-bingo.html' title='Mobile Bingo'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-315007845124402621</id><published>2007-10-10T16:31:00.001+01:00</published><updated>2007-10-10T16:31:35.440+01:00</updated><title type='text'>WPF Extension method</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;&lt;span style='color:#1f497d'&gt;I used my first extension method yesterday with WPF.  I wanted to bring a control to the foreground, that means changing its position in the child list to the last child.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d'&gt;  Parent.Children.Remove(element);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d'&gt;  Parent.Children. Add(element);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d'&gt;What I would prefer to do is call SendToFront on the collection with the appropriate child.  Since I don't have any control over the type being used to hold the collection,  I would need to resort to extension methods to get a more object style syntax.  Resulting in the following code.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d; font-family:Consolas'&gt;public static class UIElementCollectionExtensions&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d; font-family:Consolas'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d; font-family:Consolas'&gt;   public static void SendToFront(this UIElementCollection collection, UIElement element )&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d; font-family:Consolas'&gt;   {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d; font-family:Consolas'&gt;        collection.Remove(element);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d; font-family:Consolas'&gt;        collection.Add(element);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d; font-family:Consolas'&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d; font-family:Consolas'&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d'&gt;All this is well and good but it would have been virtually as elegant with an old fashioned static call on some Util class.    It then dawned on me why these are perhaps so useful, for me anyway I rely on intelli sense to see what I can do with a lot of the WPF controls, with any Util class methods I write I need to have knowledge of them, but with extension methods intelli sense can potentially pick them up.  So I refactored my code once more into a separate assembly, but placing the code into the System.Windows.Controls namespace, thus whenever I use WPF controls and reference my additional extension assembly I get my new methods.  On a large scale project I can see how this could be aid productivity.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='color:#1f497d'&gt;However there is something smelly about placing my code into someone else's namespace so on reflection I think it would be far nicer to place all my extension methods inside my own namespace, and just make sure I bring them into scope by using my extension namespace.  &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-315007845124402621?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/315007845124402621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=315007845124402621' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/315007845124402621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/315007845124402621'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/10/wpf-extension-method.html' title='WPF Extension method'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8049307330245727496</id><published>2007-10-04T10:08:00.001+01:00</published><updated>2007-10-04T10:08:11.430+01:00</updated><title type='text'>Too much reliance on encryption</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;A friend of mine was telling me recently how safe manufactures grade their safes, they don't simply say this is unbreakable/uncrackable ( only a fool would say that ).  What they do say is that they say you need X amounts of TNT or N hours to crack this safe, clearly limiting their liability you may think, but actually its useful and practical information to anyone who has a safe.  Firstly they know that there are no guarantees, but they also know what level of additional security they may need to layer on to get closer to full peace of mind.  In the case of the fact that it takes 2 hours to crack the safe the owner could employee a security guard to patrol the safe location every 1 hour, hopefully not creating a window of opportunity for the cracker to do the deed.  When you want to secure digital data similar considerations need to be taken into account.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Ive recently been involved with debating the security of biometric systems used in schools with a biometric firms Principal Sales Engineer based in the US.  The issue we have as a group is that whilst Im sure all measures today are being take to secure the data in terms of encryption technology, the plain fact remains that history has shown us that what ever cryptography we used today is likely to be compromised in a reasonable time frame say 5-10 years.  Therefore when we encrypt any sort of date we need to be aware of this since if the data has uses outside this time window then clearly we cannot rely just on this means of security.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;At this goes to the very heart of the debate in biometrics in schools, the Engineer in question dismissed are complaints about encryption technology not being adequate for 10 years plus by first acknowledging this fact ( which is a great step forward ), &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;"I personally believe their will be another breakthrough in the next 10 &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;to 15 years.  Whether is it quantum computing or the DNA processor they &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;have been working on for the last 10 years.  They can now beat a person &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;in tic tac toe.  5 years ago they could count to 10 with 80 percent &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;accuracy.  They are much faster because they don't have to calculate &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;they just know the answer.  But it is going to be a while and belive it &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;or not there are higher levels of encryption out there.  There are 512 &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;and even 1028 based encryption.  Like the computer industry, there is &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;always someone out there building a stronger based encryption."&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Further that statement shows that the industry as a whole knows we need stronger encryption because we know its only a matter of time for it to be broken, but he then goes on to say that &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;"As I said above the great thing about using encryption on keys and or &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;files is the fact that if there is a problem with a key or the actual &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;encryption you can encrypt the info with a better encryption or even &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;encrypt the encryption such as is done with 3 DES.  It is DES encrypting &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;DES encrypting DES.  The US government went from a standard of 3 DES to &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;AES 256.  Not because 3 DES had been broken…. It has not.  But because &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;they saw there were some weekensses that could be exploited and maybe in &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;the next 10 years or so it may be broken.  Now do you think that all the &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;info that they have stored in 3 DES is still in 3 DES…  I think not.  &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:10pt'&gt;They reencrypted it in the new standard."&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-size:10pt'&gt;Whilst this is all well and good there is a piece to this solution that makes the US government solution ok but not for the average school.  In that it relies on the fact that the person who is responsible for the re-encryption has guaranteed sole access to the data, in other words no one has taken an illicit copy, or more likely has some backup media, or an old hard disk.  Whilst I can imagine that the US government has plenty of physical security measures in place to make sure they own the only copy of the data, I can't imagine that the average school will have similar system in place, and let's be realistic they can't with theft being the obvious one.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;In fact I encountered a similar experience when working for Cisco, we were trying to pitch wireless networking to a large bank.  Whilst they accepted the notion that the encryption technology we had chosen prevented illegal access to the network, we could not demonstrate to them that any data sniffed off the network could not be decrypted in a time frame that still made the data useful to an outsider.  These guys were smart and did truly understand the nature of securing the business data.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So to summarise a responsible biometric manufacture would secure biometric data as best they can today, but once the software has been deployed if that data is to be truly secure it needs have sufficient physical security measures in place provided by the owner to ensure that in the future the encryption based solution still has adequate merits, the moment you do not have complete ownership of the data all bets are off...and by their own admission the biometric provider in this case said their guarantees is for appx. 10 years, in the case of biometric data for kids that data is sensitive for 60-70 years.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8049307330245727496?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8049307330245727496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8049307330245727496' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8049307330245727496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8049307330245727496'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/10/too-much-reliance-on-encryption.html' title='Too much reliance on encryption'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8399316679943063327</id><published>2007-09-28T21:55:00.001+01:00</published><updated>2007-09-28T21:55:57.582+01:00</updated><title type='text'>Patterns, Patterns everywhere</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;I've not blogged for a while now...mainly due to being  snowed under writing the developmentor's "Code Smarter with Design Patterns" course with my co-author Kevin Jones (&lt;a href='http://www.develop.com/uk/training/course.aspx?id=663'&gt;Course Details&lt;/a&gt; ) and working at a local firm ( yes Chippenham has industry).  My head is now full of a handful of posts I want to make, and I've finally found time to write this one...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Whilst writing the design pattern course I managed to stumble upon various variations of standard patterns, in the course we discuss various forms of the standard Singleton pattern.  Such as ThreadScoped singleton where each thread has access to a single instance, rather than a single instance app domain wide, this is potentially useful for preventing contention where multiple threads are competing over the use of the singleton.  But oddly enough I stumbled upon another use of the singleton pattern when developing an example of a CopyOnWrite proxy.  There are times when multiple threads request a collection of items from some object.  If all the threads are only reading from the collection life is good...If there is a potential for the threads to update the collection for their private use then we should really be returning a copy of the collection to each thread, this could be considered inefficient if the collection is only occasionally privately updated, and that is where the CopyOnWrite Proxy comes in.  By returning a proxy to the collection as opposed to the collection itself we allow ourselves to control the access to the collection in such a way as to provide access to the shared view of the collection whilst the thread is only reading but the moment it attempts to update the collection the proxy takes a copy of the collection it is providing the proxy for, and from that moment on the proxy is now wrapping up the copy.  The client is blissfully unaware of this.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Ok, so inside my proxy implementation all the methods that are deemed write operations need to determine if a copy has been made previously and if not make a copy.  In other words I will have a piece of code that I only wish to run once for the life of the object, and only once.  This sounded similar to the fact that in the case of a singleton type I only want one instance.  In my case I wanted to define a method in a class that only ever gets run once.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;For example I was creating a proxy for a List, thus inside my proxy type I implemented the method&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:14pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; Insert(&lt;span style='color:blue'&gt;int&lt;/span&gt; index, T item)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:14pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:14pt'&gt;  // Write operation, so make a private copy of the list now    &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:14pt'&gt;  MakeCopy();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:14pt'&gt;  subject.Insert(index, item);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:14pt'&gt;}&lt;/span&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;Where subject is the actual List.  Clearly I don't want MakeCopy to run every time the insert method is called just the first time on this proxy.  Simple you might say just test a Boolean flag to see if you have made a copy.   Whilst this would be guaranteed to work in a non threaded environment it would not in a threaded environment, so now you end up writing code that performs some kind of synchronization prior to determining if you have made a copy or not.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In this scenario I could simply create a method called MakeCopyIfNeccessary() and call that from each write method, and make that method do the appropriate synchronization, to do this efficiently requires double check locking.  However this got me thinking if there was a more re-usable way of doing this so that if I needed this functionality again I could somehow re-use not just the pattern but the code.  Below is a type I defined which wraps up an Action delegate such that it will only invoke the delegate once, irrespective of the number of times you call DoOnlyOnce();&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;SingletonAction&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt; onlyOnceLock = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;object&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt; SingletonAction(&lt;span style='color:#2b91af'&gt;Action&lt;/span&gt;&amp;lt;T&amp;gt; action)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;this&lt;/span&gt;.action = action;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; DoOnlyOnce(T arg)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (action != &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;                SynchronizedDoOnlyOnce(arg);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;            }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; SynchronizedDoOnlyOnce(T arg)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;lock&lt;/span&gt; (onlyOnceLock)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (action != &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;                    action(arg);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;                    action = &lt;span style='color:blue'&gt;null&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;            }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Inside my proxy class I create an instance of this type supplying it the corresponding method I wish to only be executed once.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;CopyOnUpdateList&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style='color:#2b91af'&gt;IList&lt;/span&gt;&amp;lt;T&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;IList&lt;/span&gt;&amp;lt;T&amp;gt; subject;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;SingletonAction&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;object&lt;/span&gt;&amp;gt; makeCopy;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt; CopyOnUpdateList(&lt;span style='color:#2b91af'&gt;IList&lt;/span&gt;&amp;lt;T&amp;gt; list)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;            makeCopy = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;SingletonAction&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;object&lt;/span&gt;&amp;gt;(MakeCopy);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;            subject = list;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        // ....&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style='margin-left: 36pt'&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;span style='color:blue'&gt;   public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; Insert(&lt;span style='color:blue'&gt;int&lt;/span&gt; index, T item)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;            makeCopy.DoOnlyOnce(&lt;span style='color:blue'&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;            subject.Insert(index, item);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;However if it wrapped up as an anonymous method this would be more true to the values of the singleton pattern as that way the only way the code could be invoked was via my wrapper.  Wrapping up an arbitrary method doesn't stop it from being invoked elsewhere.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt; CopyOnUpdateList(&lt;span style='color:#2b91af'&gt;IList&lt;/span&gt;&amp;lt;T&amp;gt; list)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;   makeCopy = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;SingletonAction&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;object&lt;/span&gt;&amp;gt;(delegate&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;     {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;       // Code required to perform the subject copy&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;     });&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;     subject = list;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Consolas; font-size:12pt'&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Now the "only" way that code can be run is via my wrapper class which ensures it only ever gets run once...&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8399316679943063327?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8399316679943063327/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8399316679943063327' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8399316679943063327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8399316679943063327'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/09/patterns-patterns-everywhere.html' title='Patterns, Patterns everywhere'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-5538489046777511290</id><published>2007-05-17T08:45:00.001+01:00</published><updated>2007-05-17T08:45:05.377+01:00</updated><title type='text'>Obtaining a balanced view</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;I was asked yesterday to visit Gloucestershire county council to discuss the use of biometrics in schools.  The council have set up a committee with the responsibility of forming a policy around the use of biometrics in the county; I must congratulate Gloucestershire here as they are the first government body that I'm aware of that are actually attempting to tackle this issue fully.  Currently schools are allowed to spend their money as they wish, which in one sense is great but on the other side there is always the worry that can a head of a school actually devote sufficient time to do full due diligence on a piece of technology.   Certainly in the case of biometrics a lot of the issues are not obvious and present new challenges to the school such as correctly disposing of the data in a safe and secure manor, understanding the potential long term consequences of how the data may be used and abused in the future.  These issues require you to be a technologist at minimum but really require someone to be a technologist visionary.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Investing time and effort in understanding the implications of biometrics does not need to be done by every school, it needs to be done centrally were money can be spent employing the experts from both sides of the argument to present a balanced and informed view, that will further enable the decision makers to make an efficient and informed decision.  This information needs to be made available in a prominent place, and not buried on some government web site.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I also think it's important here to include parents in the decision making process, providing them with the information in a clear and concise form.  There is precedence here, it's pretty well accepted that smoking is bad for you, people can still smoke but the government takes the responsible act of making it very clear that this could affect your long term life expectancy. Perhaps a similar mandatory warning should be made on all acceptance forms for biometric systems, just above the signature line.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;"WARNING: Some experts feel that in the future it will be possible for this information to be used to steal your child's identity"&lt;br /&gt;&lt;/p&gt;&lt;p&gt;All I'm asking for is a fair representation of the facts, surely we owe it to all decision makers to make both arguments equally available and allow them to make the decision based on the full range of facts.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-5538489046777511290?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/5538489046777511290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=5538489046777511290' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5538489046777511290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/5538489046777511290'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/05/obtaining-balanced-view.html' title='Obtaining a balanced view'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-3848137276893336946</id><published>2007-05-14T23:38:00.001+01:00</published><updated>2007-05-14T23:38:27.013+01:00</updated><title type='text'>Minimum Debugging tool set</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;This week I've been teaching DM's Effective .NET course, one theme that run through the course is the ability to debug applications in the field.  The tools in your arsenal here are the obvious ones like perfmon, but also the native windows debugging.  The native debugger can be used to take snap shots of the suspect process (dump's seems to get a giggle from a few students).  You therefore need to put the debugger on the client's machine, the typical way to do this is to download the debugging tools for windows, this is a   reasonable size once unzipped 37MB...This includes a graphical debugging a few other bits and bobs, whilst these tools are useful on a developers machine they are not needed to take a snapshot  and therefore not relevant for anyone other than a developer.  This prompted a question from a student as to what is the minimum set of files needed to take a dump from a users machine. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;After a few trial and errors we came up with the following list of files&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;    tlist.exe&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    dbgeng.dll&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    dbghelp.dll&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    adplus.vbs&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    cdb.exe&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This results in a 4.6 MB unzipped install for a client's machine; this is more of a reasonable size that could be included in all employees desktop configuration.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-3848137276893336946?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/3848137276893336946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=3848137276893336946' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3848137276893336946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/3848137276893336946'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/05/minimum-debugging-tool-set.html' title='Minimum Debugging tool set'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-8275579997225094470</id><published>2007-03-21T18:25:00.001Z</published><updated>2007-03-21T18:25:33.279Z</updated><title type='text'>Free Running Threads</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;Last week I was teaching Developmentor's Effective .NET 2 course, as part of that course we spend at least a day looking at various patterns for building multi threaded applications.  With the rise of multi core machines it is becoming increasingly more important to write algorithms that can scale with the availability of new cores.  One of the topics we cover is thread safety, and I typically write an application that simply performs an i++ operation on multiple threads,  on a single core does not typically generate a problem but on a multi core means we rarely get the value we expected since i++ is in fact multiple CPU instructions, e.g&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Lucida Console'&gt;MOV R0,i&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Lucida Console'&gt;INC R0&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Lucida Console'&gt;MOV i,R0&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;One thread could perform the load of i into a register and at the same time another is also doing this thus they both cause i to be simply incremented by 1 and not by 2.  To solve this problem we have a variety of synchronization techniques at our disposal some are lighter weight than others&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Interlocked.Increment , Monitor.Enter/Exit and OS synchronization primitives like Mutex&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;In my stress test I conducted in class I had multiple threads updating a single integer...First I demonstrated on a multi core machine that i indeed didn't have the correct value after 10 threads had attempted to increment it 10000 times.  I then moved to using Interlocked.Increment and now everything was as expected for the result, but it was slower than a simple i++.  All well and good so far...I then moved to using Monitor.Enter and Monitor.Exit and to my amassment that took pretty much the same time as Interlocked...so as all engineers do...we run it again cause that result was just a glitch....but after numerous runs it kept coming out the same....So when I first developed this demo I did so on a single core machine and this was its first outing on a dual core, so what went wrong...all my multi threading life I've been told that interlocked is far cheaper than the heavier weight mutex style of synchronization.  I then re-ran the demo with CPU Affinity set to a single CPU, and got the results I would have expected with Interlocked being at least an order of magnitude quicker than mutex&lt;br /&gt;&lt;/p&gt;&lt;p&gt;During the lab break I stepped back and had a think, about what could have caused this, the light eventually went on in that all the threads were in fact sharing a common variable, with dual core each core  is going to be attempting to cache this value, this has a very negative effect on the cache, why well the cores try and maintain cache coherency by marking parts of the cache dirty when they update them, and forcing the other core to reload its data from main memory...If this wasn't the case in our example we would have had the wrong numbers again...So ok possibly what you would have expected....however the process of marking a piece of memory as dirty is not as simple as marking a single word, its less granular than that the core will mark whats called a cache line as dirty meaning any data on the same cache line as the value being updated is effectively marked as invalid.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So imagine two integers next two each other in memory.  Thread A increments integer one and Thread B increments integer two, from a high level programming language perspective this is perfect, each thread has its own private resource and there is no need to synchronise and the threads therefore run freely...The perfect threaded app....however not so fast if both integers occupy the same cache line...we take a performance hit...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;To demonstrate this fact I wrote some code that simply implements  a parallel i++.  There are three scenario's&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Interlocked.Increment( ref i )&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Interlocked.Increment( ref ManyCounters[&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:#2b91af'&gt;Thread&lt;/span&gt;.CurrentThread.ManagedThreadId ] )&lt;/span&gt;&lt;br /&gt;				&lt;/li&gt;&lt;li&gt;&lt;div&gt;Interlocked.Increment( ref ManyCounters[Thread.CurrentThread.ManagedThreadId * 10000 ] )&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Whilst the last two variants will not produce the correct total, the middle version shows that although the threads are not sharing the same variable the fact that the fact that they probably all live on the same cache line is the crucial factor.  Below is the results of running the code using 1 and 2 threads.  In the first case, with the high level of contention we see that a single thread would have been more efficient.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Lucida Console; font-size:8pt'&gt;Single shared counter with 1 Threads took 00:00:00.2065516&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Lucida Console; font-size:8pt'&gt;Single shared counter with 2 Threads took 00:00:00.4303586&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;In the second case with multiple counters we are still taking a hit on performance even though the counters are different ints, and thus we are not incrementing the same location&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Lucida Console; font-size:8pt'&gt;Multiple counters with 1 Threads took 00:00:00.2184554&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Lucida Console; font-size:8pt'&gt;Multiple counters with 2 Threads took 00:00:00.5177658&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Only in this last case were we ensure the counters are not on the same cache line do we see both cores being used efficiently.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Lucida Console; font-size:8pt'&gt;Multiple Sparse Counters ( ~4k apart ) with 1 Threads took 00:00:00.2180101&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Lucida Console; font-size:8pt'&gt;Multiple Sparse Counters ( ~4k apart ) with 2 Threads took 00:00:00.1603323&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;So what does all this mean, well it certainly shows that just because your code at a high level programming language has no contention it doesn't mean that it will not have contention when the code finally meets the hardware.  This is obviously a big issue and more so with virtualisation in .NET, how do I know the size of the cache lines, or how my data will be laid out in memory...Computing just got fun again.....&lt;a href='http://www.beaconsoft.co.uk/Downloads/ScalingIncrement.zip'&gt;Code&lt;/a&gt;&lt;br /&gt;			&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-8275579997225094470?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/8275579997225094470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=8275579997225094470' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8275579997225094470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/8275579997225094470'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/03/free-running-threads_21.html' title='Free Running Threads'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-117093349865816110</id><published>2007-02-08T11:18:00.000Z</published><updated>2007-02-08T11:18:37.940Z</updated><title type='text'>Reduce your risk; only store what you really need</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;I've been drawn further into the campaign to prevent biometric information being used by schools, on Tuesday I attended a briefing session for MP's with the aim to highlight the issues with adopting this technology in the context of school children.  The BBC were present and did an article for BBC online..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;http://news.bbc.co.uk/1/hi/uk_politics/6336799.stm&lt;br /&gt;&lt;/p&gt;&lt;p&gt;What we as campaigners are increasingly finding hard to understand is how the department for education fails to understand the difference between data that has a relatively short validity and immutable data that last a life time ( I can't change my finger print)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;For me one of the best quotes from Dfes with regard to schools holding biometric data is:-&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;"They are well used to handling all kinds of sensitive information to comply with data protection and confidentiality laws. &lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt; Schools have historically failed here; a forensic computer science faculty bought hard drives off ebay, and extracted school records (&lt;a href='http://www.theregister.co.uk/2005/02/17/hard_drive_data/'&gt;http://www.theregister.co.uk/2005/02/17/hard_drive_data/&lt;/a&gt; ).  A colleague also told me recently how he took a school computer out of a skip...Personally I don't condemn the schools here after all their primary focus is on education and not on securing personal information.  In fact this is also the case in business the IT system the security are all additional burdens which do not enhance the core functionality of the business, it is seen as a necessary evil, and you often find these are given second or third rate priorities.&lt;span style='font-family:Verdana'&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Information security can never be guaranteed and so we should therefore only gather the least amount of information required to perform our function.  Software engineers have been aware of running applications with least privilege, thus limiting the risk that there application exposes to a system if it was to be hacked; even Microsoft is adopting this strategy at last with Vista.  This therefore poses the question do schools need biometric information in order to educate our children? If the answer is no then it should not be used in schools...since this creates a further burden on a system which already showing signs of failing under the current security workload.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-117093349865816110?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/117093349865816110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=117093349865816110' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/117093349865816110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/117093349865816110'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/02/reduce-your-risk-only-store-what-you.html' title='Reduce your risk; only store what you really need'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-117043523308285226</id><published>2007-02-02T16:53:00.000Z</published><updated>2007-02-02T16:53:53.096Z</updated><title type='text'>Custom ToString() for Flag based Enums, and a splatter of Unit Testing</title><content type='html'>&lt;span xmlns=''&gt;&lt;p&gt;A project that I'm currently working on has a enum type, where the enum is defined like so&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;[Flags]&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;enum&lt;/span&gt; EventDayMask&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; NONE = 0,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; SUNDAY = 1,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; MONDAY = 2,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; TUESDAY = 4,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; WEDNESDAY = 8,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; THURSDAY = 16,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; FRIDAY = 32,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; SATURDAY = 64&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Calling ToString on a value of type EventDayMask would result in a comma separated list of the various set bits..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;EventDayMask weekend = EventDayMask.SATURDAY | EventDayMask.SUNDAY;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;Console.WriteLine( weekend.ToString() );&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Would produce SATURDAY,SUNDAY..Whilst this is a massive improvement on what we had with C and C++ I in fact would like a more appealing string like Saturday, Sunday.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;You can't override ToString for Enum's which means you can't write your custom string generate as part of the enum class.  There are many blog posts on how you can achieve this for a non Flagged based enums, by applying custom attributes to your enum definition and then having a static method on a Utils class that first determines the value of the enum and then determines if there is a custom attribute associated with that value and if so uses the string associated with that custom attribute.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;E.g&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;enum&lt;/span&gt; EventDayMask&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; NONE = 0,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;[Description("Sunday")]&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; SUNDAY = 1,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;[Description("Monday")] // etc..&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; MONDAY = 2,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; TUESDAY = 4,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; WEDNESDAY = 8,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; THURSDAY = 16,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; FRIDAY = 32,&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt; SATURDAY = 64&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;However with flag based enum's it gets a bit more complex, since an enum does not have a single value but a combination of many valid values, as in the DayMask example above.  To extend the technique to Flag'd based enums you need to effectively test the enum value against each possible flag value.  I managed to write a version that did this by stepping through each possible value and performing a logical "AND" against the underlying enum value, and that worked fine, until I added an or'd value to my enum definition.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;public enum EventDayMask&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;    ...&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;     [Description("Weekend")]&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;    WEEKEND = SATURDAY | SUNDAY&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:12pt'&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;The built in ToString() works as expected if the underlying value is SATURDAY | SUNDAY it outputs WEEKEND.  Obviously I wanted the same behaviour, it was at this point that I realised this small task was now going to escalate, a quick cup of tea latter and I decided to change my approach why not simply use the built in ToString() to generate the initial string and then replace each of its component parts with the value stored in the attribute.  This simplified the code greatly..the downside being that  I'm tightly coupled with the output format of Enum.ToString().  To counteract this I have a handful of unit tests as part of the project that tests this functionality, so if MS ever changed the formatting algorithm for Enum.ToString(), I'm alerted immediately..This for me is another example why unit testing is so powerful, I can make expedient decisions that I wouldn't have dared made without them....&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;[&lt;span style='color:#2b91af'&gt;AttributeUsage&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;AttributeTargets&lt;/span&gt;.Field,AllowMultiple=&lt;span style='color:blue'&gt;false&lt;/span&gt;)]&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;EnumValueDescriptionAttribute&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;Attribute&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt; EnumValueDescriptionAttribute(&lt;span style='color:blue'&gt;string&lt;/span&gt; description)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            Description = description;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt; Description;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;    &lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;EnumUtils&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;const&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;char&lt;/span&gt; ENUM_FLAGGED_VALUE_SEPERATOR_CHARACTER = &lt;span style='color:#a31515'&gt;','&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt; EnumToString(&lt;span style='color:#2b91af'&gt;Enum&lt;/span&gt; enumValue)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;StringBuilder&lt;/span&gt; enumValueAsString = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;StringBuilder&lt;/span&gt;();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Type&lt;/span&gt; enumType = enumValue.GetType();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt;[] enumToStringParts = enumValue.ToString().Split(ENUM_FLAGGED_VALUE_SEPERATOR_CHARACTER);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;foreach&lt;/span&gt; (&lt;span style='color:blue'&gt;string&lt;/span&gt; enumValueStringPart &lt;span style='color:blue'&gt;in&lt;/span&gt; enumToStringParts)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;FieldInfo&lt;/span&gt; enumValueField = enumType.GetField(enumValueStringPart.Trim());&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;EnumValueDescriptionAttribute&lt;/span&gt;[] enumDesc = enumValueField.GetCustomAttributes(&lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;EnumValueDescriptionAttribute&lt;/span&gt;), &lt;span style='color:blue'&gt;false&lt;/span&gt;) &lt;span style='color:blue'&gt;as&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;EnumValueDescriptionAttribute&lt;/span&gt;[];&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (enumValueAsString.Length &amp;gt; 0)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                    enumValueAsString.Append(ENUM_FLAGGED_VALUE_SEPERATOR_CHARACTER);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;if&lt;/span&gt; (enumDesc.Length == 1)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                    enumValueAsString.Append(enumDesc[0].Description);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;else&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                    enumValueAsString.Append(enumValueStringPart);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;                }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;            }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;return&lt;/span&gt; enumValueAsString.ToString();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        } &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New'&gt;&lt;span style='font-size:10pt'&gt;    }&lt;/span&gt;&lt;span style='font-size:12pt'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-117043523308285226?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/117043523308285226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=117043523308285226' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/117043523308285226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/117043523308285226'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/02/custom-tostring-for-flag-based-enums.html' title='Custom ToString() for Flag based Enums, and a splatter of Unit Testing'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-116860028977116300</id><published>2007-01-12T11:11:00.000Z</published><updated>2007-01-12T11:11:29.826Z</updated><title type='text'>TransactionScope and DataAdapters</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Recently I had to write some code that persisted changes too two DataTable's to a SQL Server database, with both updates inside a single transaction.  So since I was using .NET 2.0 I decided to use TransactionScope.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;using( TransactionScope tx = new TransactionScope()))&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;    firstTableAdapter.Update( firstTable );&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;    secondTableAdapter.Update( secondTable );&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;    tx.Complete();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;I was careful to ensure that both adapters used the same database connection object, however there was still a nasty side effect. First a bit of background&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In order for a resource manager (in this case SQL Server) to take part inside a transaction it must first enlist in the transaction, SQL server determines if to do this when a connection is opened.  Opening a connection when there is a transaction associated with the current thread will result in SQL server placing that connection inside a transaction, if no other enlistment has happened then SQL server will create a local transaction and thus manage the transaction.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;If another resource manager wishes to enlist in the transaction then no one resource manager can be responsible for coordinating the transaction and the DTC is invoked (Distributed Transaction Coordinator), the role of the DTC is to ensure the properties of the transaction across multiple resources.  Such that a failure to commit one set of resources through one resource manager causes a rollback in the other.  SQL Server is the only resource manager that currently allows the promotion of a local transaction to a distributed transaction; other resource manages like MSMQ will always create a distributed transaction irrespective of the number of previous enlistments.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Ok, so to sum up if you enlist multiple resource managers inside a single transaction the DTC is invoked and the transaction becomes a distributed transaction.  The obvious consequence of this is that the transaction management is now more expensive.  So we obviously want to avoid having a distributed transaction unless we really need to.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;When first playing with TransactionScope we can end up with a distributed transaction when from a high level logical perspective it might seem strange.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;&lt;span style="color:blue"&gt;using&lt;/span&gt;( TransactionScope tx = &lt;span style="color:blue"&gt;new&lt;/span&gt; TransactionScope() )&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt; {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;       conn.Open();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;        // Do DB Work&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;      conn.Close();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;      conn.Open();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;        // Do DB Work&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;      conn.Close();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;      tx.Complete();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt; }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;           &lt;br /&gt; &lt;/p&gt;&lt;p&gt;            &lt;br /&gt; &lt;/p&gt;&lt;p&gt;In the above example our transaction is promoted to a distributed transaction, why because on the second open SQL Server will attempt to enlist in the transaction, because there is already a transaction enlisted System.Transaction will attempt to promote the existing transaction to be managed by the DTC, and the new transaction will also be managed by the DTC.  This does seem odd at first since you are in fact only using a single Resource Manager, there is a rumour that this will be fixed in the future.  If you do not have the DTC service running on your machine the code above will throw an exception.  If you have the DTC running then the code runs to completion, and you are non the wiser of the promotion, except for a slight pause.  To see when the promotion has taken place simply make a call to the function below at the various points to see the transaction identifier.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:blue"&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style="color:blue"&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style="color:blue"&gt;void&lt;/span&gt; PrintTransaction(&lt;span style="color:teal"&gt;Transaction&lt;/span&gt; transaction)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;br /&gt;					&lt;span style="color:teal"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:maroon"&gt;"Local Id = {0}"&lt;/span&gt; , transaction.TransactionInformation.LocalIdentifier );&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;br /&gt;					&lt;span style="color:teal"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:maroon"&gt;"Global Id={0}"&lt;/span&gt; , transaction.TransactionInformation.DistributedIdentifier);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Back to the data adapter example, when the data adapter attempts to do an update if the connection is not currently open it opens the connection and performs the update.  If it opens the connection it would be polite for it close the connection when it is done.  So when the first Update runs on opening the connection it creates a local transaction which gets enlisted, when the second update runs it also needs to open the connection and so it enlists a second transaction and thus causes the behaviour observed above.  To fix the problem we simply have to ensure that the connection is only opened once.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;using( TransactionScope tx = new TransactionScope()))&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;    conn.Open();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;    try&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;    {&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;        firstTableAdapter.Update( firstTable );&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;        secondTableAdapter.Update( secondTable );&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;        tx.Complete();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;finally&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;    conn.Close();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Now when the calls are made to update the data adapter sees that the connection is already open and thus the sql commands now run in the context of the existing transaction and no promotion is necessary.  It is therefore essential that when you create the data adapters you create them with the same connection object you are using inside the transaction scope.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;All this poses the question how can I ensure that I don't accidently cause a promotion to take place; there are two solutions that come to mind&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Disable the DTC on your machine&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add a Debug.Assert prior to calling the outer Complete&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The only way I could find to determine if a promotion had happened was to look at the Distributed Transaction Identifier.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;&lt;span style="color:teal"&gt;Debug&lt;/span&gt;.Assert(IsInDistributedTransaction() == &lt;span style="color:blue"&gt;false&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;tx.Complete();&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;...  &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;&lt;span style="color:blue"&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style="color:blue"&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style="color:blue"&gt;bool&lt;/span&gt; IsInDistributedTransaction()&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;				&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;br /&gt;					&lt;span style="color:blue"&gt;return&lt;/span&gt; ((&lt;span style="color:teal"&gt;Transaction&lt;/span&gt;.Current != &lt;span style="color:blue"&gt;null&lt;/span&gt;) &amp;amp;&amp;amp;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;&lt;span style="font-size:10pt"&gt;         (&lt;span style="color:teal"&gt;Transaction&lt;/span&gt;.Current.TransactionInformation.DistributedIdentifier != &lt;span style="color:teal"&gt;Guid&lt;/span&gt;.Empty));&lt;/span&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;So whilst TransactionScope has certainly improved the programming model for transactions by hiding a lot of the complexities required for distributed transactions it is essential to understand how it works if you are to avoid accidently creating a distributed transaction.&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-116860028977116300?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/116860028977116300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=116860028977116300' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116860028977116300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116860028977116300'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/01/transactionscope-and-dataadapters.html' title='TransactionScope and DataAdapters'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-116800837581801608</id><published>2007-01-05T14:46:00.000Z</published><updated>2007-01-05T15:03:34.396Z</updated><title type='text'>WPF Pong</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Couldn't keep still over the xmas break, my kids were playing some of those classic games we used to play as kids although now inside a tiny console you plug in to your tv.  This got me thinking about writing a classic game using WPF, not being much of a games writer I kept things simple and decided to implement the classic game Pong...My main aim is to continue to ramp up on WPF, one area I wanted to explore further was the use of Content Templates and styles, what I wanted to be able to do was not only clearly separate UI layout from UI behaviour but also allow different Skins to be applied to the game one being the classic black and white look another being a more 21&lt;sup&gt;st&lt;/sup&gt; Centaury look and feel.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;To implement Skining in WPF you make use of Styles contained in resource dictionaries, when a control makes reference to a named style the control tree is walked for each control its resource dictionary is searched for a style by that name if none is found the search continues up the tree.  Styles allow you to set properties of the control, very similar to ASP.NET skins.  So in the case of the bats you can set a style that sets the colour, width and length of the bats.  You can then apply this style to both player one's and player two's bat keeping both bats looking the same.   In order to allow the interchanging of Skins I placed all the resource definitions into their own resource dictionaries.  Each Skin is then an instantiation of a resource dictionary, when the window is launched I simple associate my window resource dictionary with the currently selected skin.  When any of the controls wish reference styles located in resources they walk up the control tree looking for the resource and should find it in the resource dictionary associated with the window.  If the user wishes to change the current skin I simply change the resource dictionary associated with the window and the look feel changes to reflect the new skin.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New; font-size:10pt"&gt;&lt;span style="color:blue"&gt;this&lt;/span&gt;.Resources = newSkin;// this is the current window&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Below is an extract from GameWindow.xaml, the style of the stack panel is defined through a resource named StatusPanel, notice that DynamicResource is used as opposed to StaticResource.  If you want to have any changes in resources immediately reflected then you need to bind using a DynamicResource, these are slightly more expensive since the infrastructure needs to keep track of any changes. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New"&gt;&lt;span style="font-size:10pt"&gt;&lt;span style="color:blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon"&gt;StackPanel&lt;/span&gt;&lt;span style="color:blue"&gt;&lt;br /&gt;						&lt;/span&gt;&lt;span style="color:red"&gt;Grid.Column&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;"&lt;span style="color:blue"&gt;0&lt;/span&gt;"&lt;span style="color:blue"&gt;&lt;br /&gt;						&lt;/span&gt;&lt;span style="color:red"&gt;Grid.Row&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;"&lt;span style="color:blue"&gt;3&lt;/span&gt;"&lt;span style="color:blue"&gt;&lt;br /&gt;						&lt;/span&gt;&lt;span style="color:red"&gt;Style&lt;/span&gt;&lt;span style="color:blue"&gt;=&lt;/span&gt;"&lt;span style="color:blue"&gt;{DynamicResource StatusPanel}&lt;/span&gt;"&lt;span style="color:blue"&gt; &amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;One really cool feature of WPF is the ability to change the inner content of a control via the template property.  I used this to great effect when defining for displaying the scores using block character style numbers.  I used a data trigger to select the appropriate inner content template based on the value of the score.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;When I have some more free time I want to add WPF animation effects so that the bat shudders when the ball hits it...Oh and my QA engineer ( AKA my son ) wants to enhance the game so you can move the bats forwards and backwards too...( "Just like real tennis." )&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Oh I also perhaps need to have some instructions in regard to keys etc...but for now&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A and Z player one&lt;br /&gt;&lt;/p&gt;&lt;p&gt;K and M player two&lt;br /&gt;&lt;/p&gt;&lt;p&gt;And Space to serve..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;First to 9 wins...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;When I first started hearing about WPF and how designers would now rule over UI I I started to get the same feelings I had when I first saw VB 6, but what seems to be coming clear whilst the designers can really do cool stuff they really need to have good exposure to the underlying model, so there certainly is still a significant role for us UI developers in  exposing the appropriate information all be it perhaps slightly removed from the coal face...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;You can download the full source from &lt;a href="http://www.beaconsoft.co.uk/Downloads/Pong.zip"&gt;WPFPong&lt;/a&gt; , or for any Click Once Jen fans you can install it via &lt;a href="http://www.beaconsoft.co.uk/Pong/publish.htm"&gt;ClickOnce&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-116800837581801608?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/116800837581801608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=116800837581801608' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116800837581801608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116800837581801608'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2007/01/wpf-pong.html' title='WPF Pong'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-116146604874321854</id><published>2006-10-21T22:22:00.000+01:00</published><updated>2006-10-21T22:27:28.780+01:00</updated><title type='text'>SynchronizationContext assists layering</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Having just got back from two weeks travelling I was confronted with the need that my oldest daughter needs to learn her times tables for a tester after half term.  Being away a lot and the children having loads of after school clubs etc means we often find it hard to find the right moment to practice.  So I decided to write an app to help test them on it…Ok so I’m sure there are tons of them out there…but you can’t beat a home grown solution ;-)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Seriously there is a couple of areas I am focusing on at the moment, &lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;ul&gt;&lt;li&gt;&lt;div&gt;Ramping up for DM’s .NET architecture course.&lt;br /&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;WPF.  &lt;br /&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;p&gt;This seemed like a good exercise where I could put both these skills to good use.  Now even DM instructors have time pressures this app needed to be written like yesterday if the kids are to start using it to get ready for their test.  My WPF skills aren’t there yet that I could confidently build the UI that quick, but in a few weeks I do want to add a WPF gui.   So this creates a great architectural opportunity for me to structure the solution into clear layers…Model, View and Controller.  The View and Controller layer is specific to WinForms and I obviously want to write as little code here as possible, putting most of my focus on the Model, in this case a Times Table Test engine.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;First I built the model defining a type to represent the test, and exposing properties for three possible answers and a running score.  The type also had methods for requesting the next question and submitting an answer.   In order to make the view be updated by changes in the model I had to implement the INotifyPropertyChanged interface on each model type in order for them  to notify the UI of any changes to the model.&lt;br /&gt;&lt;/p&gt;&lt;p&gt; Then I moved onto building a form to display the current question.  Labels were used to pose the question,  and to display the score etc.  The  possible answers were represented by buttons.  Having laid out the form it was then just a question of wiring up, the various labels and buttons to display the correct values, this was achieved through the use  databinding via bindingSources, all the wiring up done inside the designer.  I then had to wire up the actions for the various buttons to communicate the users response to the question and to move the question forward.    But So far so good…virtually no UI code written.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;However whilst this was ok to make the app really useful the user needs to enter the response in a finite period of time.  So this created two options implement a timer in the UI layer or in the model…For me I obviously wanted to place it into the model since that piece of code would be reused when I implement the WPF UI.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;So off I went and added a Timer thread to my model, the activity on this timer thread would cause various bound properties in the model to be updated, which then had the effect of firing PropertyChanged events to all objects bound to these properties.  Since some of these bindings where to UI components this would result in the UI component being updated on a thread other than the thread used to create the UI component.   Attempting to update a UI component on a foreign thread is technically not allowed, and in .NET 2.0 if you have a debugger attached and you attempt to do so you get a cross thread exception…to my surprise I didn’t get one…just the update’s failed to be propagated to the UI.   This I thought was a bit odd…but since the update didn’t happen I guess it’s by design Im not 100% sure of the exact reasoning behind this..Anyway for me I need to fix this situation since I did want my UI to be updated.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In order to solve this problem I would need to cause the event to actually be delivered on the UI thread.  The conventional way to do this in WinForms is to use a pair of methods on every control called InvokeRequired and BeginInvoke.  But this would mean that my model code would need knowledge of winforms to ensure that all events fired on the UI thread Yuk and breaks my architectural model.&lt;br /&gt;&lt;/p&gt;&lt;p&gt; There is however a more general way of doing this using something called SynchronizationContext, this is an abstract class that provides a way of marshalling a delegate onto a specific thread.  You can ask WinForms for the current SynchronizationContext and it will return an object that can be used to post work back onto the UI thread.  You write your code against the abstract class, and assuming other UI implementations that require thread affinity also support this then my mode can be written just the once.  In fact WPF does have support for this so cool…the model can be written to deliver PropertyChanged events on the correct thread.  To ensure my property events are marshalled onto the appropriate thread I have a method which looks as follows.&lt;br /&gt;&lt;/p&gt;&lt;span style="font-family:Lucida Console; font-size:12"&gt;&lt;p&gt;&lt;span style="color:blue"&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style="color:blue"&gt;void&lt;/span&gt; SafePropertyChangeNotification(&lt;span style="color:blue"&gt;string&lt;/span&gt; property)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;					&lt;span style="color:blue"&gt;if&lt;/span&gt; (syncCtx != &lt;span style="color:blue"&gt;null&lt;/span&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    syncCtx.Post(&lt;span style="color:blue"&gt;delegate&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;    {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;       OnPropertyChanged(&lt;span style="color:blue"&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style="color:teal"&gt;PropertyChangedEventArgs&lt;/span&gt;(property));&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    } , &lt;span style="color:blue"&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  }&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;					&lt;span style="color:blue"&gt;else&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;  {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;     OnPropertyChanged(&lt;span style="color:blue"&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style="color:teal"&gt;PropertyChangedEventArgs&lt;/span&gt;(property));&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  }&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;What I’m  struggling to understand is why they MS never added support in the BindingSource type to perform the marshalling operation, they are after all detecting the attempt to perform a cross thread operation and silently ignoring it, giving you the option to configure the binding source to marshal the update would have been dead cool.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Anyway the SynchronizationContext does allow me to decouple my model from my UI implementation, and does allow me to write a single piece of marshalling code that will work with WPF or WinForms..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The first version of the times table tester is now complete, the UI layer is extremely thin…and I even managed to deploy it in our home network using ClickOnce…I know scary I actually taught the kids how to just say ok to the not trusted publisher prompt….&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Over the next few weeks I’m going to build a WPF version of the UI  and assuming no hidden gotcha’s Im just simply going to replace the UI layer with a new one&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;You can download the full code from my &lt;a href="http://www.beaconsoft.co.uk/download.html"&gt;download page&lt;/a&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;        &lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console; font-size:12"&gt;&lt;br /&gt;				&lt;/span&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-116146604874321854?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/116146604874321854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=116146604874321854' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116146604874321854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116146604874321854'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/10/synchronizationcontext-assists.html' title='SynchronizationContext assists layering'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-116048647529248846</id><published>2006-10-10T14:16:00.000+01:00</published><updated>2006-10-10T14:21:15.300+01:00</updated><title type='text'>Korean’s get excited over VSTS</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Whilst teaching the other week Jason pointed me to this cool VSTS video where Korean developers had to make their own jingle to spread the news….&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Check out the   &lt;a href="http://blog.naver.com/dazzilove/60018738226"&gt;Video&lt;/a&gt;  ignore all the requests to install the language packs unless you want Korean characters on your machine..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-116048647529248846?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/116048647529248846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=116048647529248846' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116048647529248846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116048647529248846'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/10/koreans-get-excited-over-vsts.html' title='Korean’s get excited over VSTS'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-116048581722788845</id><published>2006-10-10T14:04:00.000+01:00</published><updated>2006-10-10T14:10:17.270+01:00</updated><title type='text'>BioGuard fingerprinting booted out</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;If you have read my earlier posts you may have read my rants on how my kids primary school was attempting to implement fingerprinting for school registration.  Finally after a whole year and some money they eventually got it that the idea was just plain dumb….how they ever expected to integrate such a system such that they had a reliable and fault tolerant registration system at a reasonable price was beyond me and any else who had any reasonable amount of IT experience.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So whilst I’m pleased I’m just hoping that no other school gets approached by &lt;a href="http://www.bio-guard.net/"&gt;Bio Guard&lt;/a&gt; or its resellers in the UK.  It also made me chuckle today as their web site hinted that finger prints are globally unique something we now know to be false.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-116048581722788845?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/116048581722788845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=116048581722788845' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116048581722788845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116048581722788845'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/10/bioguard-fingerprinting-booted-out.html' title='BioGuard fingerprinting booted out'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-116048243800511957</id><published>2006-10-10T13:08:00.000+01:00</published><updated>2006-10-10T13:13:58.140+01:00</updated><title type='text'>More than just coffee</title><content type='html'>&lt;span xmlns=""&gt;&lt;span style="color:#1f497d"&gt;&lt;p&gt;The whole identity theft took a new twist today whilst at Starbucks I noticed that  the electronic credit card machine had a sticker  on it and in big letters were the Network Address of the device and other network details…..Wow some hacker would just luv to lap those numbers up along with their espresso….The nice girl behind the counter did remove it…&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-116048243800511957?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/116048243800511957/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=116048243800511957' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116048243800511957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/116048243800511957'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/10/more-than-just-coffee.html' title='More than just coffee'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115747924674308624</id><published>2006-09-05T18:27:00.000+01:00</published><updated>2006-09-05T19:02:48.146+01:00</updated><title type='text'>Slicker Labels</title><content type='html'>Whilst thinking up some more interesting WinForms demo's I just thought Id have a go and at making a the bog standard label control a bit more interesting...so I knocked up a new version that fades text in and out when the label's text property is modified.&lt;br /&gt;&lt;br /&gt;The Source code can be downloaded from my &lt;a href="http://www.beaconsoft.co.uk/download.html"&gt;downloads page&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115747924674308624?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115747924674308624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115747924674308624' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115747924674308624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115747924674308624'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/09/slicker-labels.html' title='Slicker Labels'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115377388735891390</id><published>2006-07-24T21:41:00.000+01:00</published><updated>2006-07-24T21:44:47.363+01:00</updated><title type='text'>WHAK a Mole WPF</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Just started to play with WPF, and just had to port Jason’s W infamous WHAK a mole game to WPF.  Hasn’t exactly pushed the boundaries of my GPU, but more about starting  getting to grips with XAML, WPF event model and inner content.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.beaconsoft.co.uk/download.html"&gt;Download Source&lt;/a&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115377388735891390?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115377388735891390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115377388735891390' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115377388735891390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115377388735891390'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/whak-mole-wpf.html' title='WHAK a Mole WPF'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115272962073607893</id><published>2006-07-12T19:36:00.000+01:00</published><updated>2006-07-12T19:40:20.896+01:00</updated><title type='text'>Every OS Sucks</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Currently teaching a DM Guerrilla, and we have been playing some short funny geeky type movies, a student offered this one to be considered….&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.deadtroll.com/index2.html?/video/ossuckscable.html~content"&gt;Every OS Sucks…&lt;/a&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115272962073607893?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115272962073607893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115272962073607893' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115272962073607893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115272962073607893'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/every-os-sucks.html' title='Every OS Sucks'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115228809018825856</id><published>2006-07-07T16:58:00.000+01:00</published><updated>2006-07-07T17:07:30.826+01:00</updated><title type='text'>Visual Studio and ASP.NET Master Pages</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I finally got tierd of the bug in the Visual studio designer for ASP.NET master pages. The issue is this, if you don’t hardcode the master page for the page in the page itself the designer will not see that you are using master pages, even if you define one in the pages section of web.config. This greatly defeats one of the objectives of master pages in that I would like to tweak the master page at deployment time, and the default behavior is page value overrides config file.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Possible solutions are have a default.master page, and make all pages point to that. Then have the actual master pages as separate files and simply copy over the default.master with the one you want at deployment time.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;That seems clunky to me, so another option would be to make it use the value in web.config as opposed to the one defined on the page. You can do this by creating a new class that sits between your form and the System.Web.UI.Page class. This class will simply inspect the value held in web.config and if its set override the page setting.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;span style="font-family:Lucida Console;font-size:12;"&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;u&lt;span style="color:blue;"&gt;sing&lt;/span&gt; System.Data;&lt;br /&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Configuration;&lt;br /&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Web;&lt;br /&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Web.Security;&lt;br /&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Web.UI;&lt;br /&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Web.UI.WebControls;&lt;br /&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Web.UI.WebControls.WebParts;&lt;br /&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Web.UI.HtmlControls;&lt;br /&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Configuration;&lt;br /&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Web.Configuration;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Lucida Console;"&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:teal;"&gt;SiteMaster&lt;/span&gt; : &lt;span style="color:teal;"&gt;Page&lt;br /&gt;&lt;/span&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:Lucida Console;"&gt;&lt;span style="color:blue;"&gt;  protected&lt;/span&gt; &lt;span style="color:blue;"&gt;override&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; OnPreInit(&lt;span style="color:teal;"&gt;EventArgs&lt;/span&gt; e)&lt;br /&gt;  {&lt;br /&gt;&lt;span style="color:teal;"&gt;    PagesSection&lt;/span&gt; pagesSection = (&lt;span style="color:teal;"&gt;PagesSection&lt;/span&gt;) &lt;span style="color:teal;"&gt;ConfigurationSettings&lt;/span&gt;.GetConfig(&lt;span style="color:maroon;"&gt;"system.web/pages"&lt;/span&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:Lucida Console;"&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;    if&lt;/span&gt; (pagesSection.MasterPageFile != &lt;span style="color:teal;"&gt;String&lt;/span&gt;.Empty)&lt;br /&gt;    {&lt;br /&gt;&lt;span style="color:blue;"&gt;      this&lt;/span&gt;.MasterPageFile = pagesSection.MasterPageFile;&lt;br /&gt;    }&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:Lucida Console;"&gt;&lt;p&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:Lucida Console;"&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;    base&lt;/span&gt;.OnPreInit(e); &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;"&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Simply modify your code behind file to look like&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console;font-size:12;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;partial&lt;/span&gt; &lt;span style="color:blue;"&gt;class &lt;/span&gt;&lt;span style="color:teal;"&gt;DefaultForm&lt;/span&gt; : &lt;span style="color:teal;"&gt;SiteMaster&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;And you will now get the master page as defined in the web.config. For pages you want to set by override the site default continue to derive directly from System.Web.UI.Page.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115228809018825856?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115228809018825856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115228809018825856' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115228809018825856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115228809018825856'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/visual-studio-and-aspnet-master-pages.html' title='Visual Studio and ASP.NET Master Pages'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115225883495108546</id><published>2006-07-07T08:49:00.000+01:00</published><updated>2006-07-07T09:00:25.010+01:00</updated><title type='text'>Finger printing in schools just gets hotter…</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;A while back I mentioned that the primary school my children are attending was planning to introduce fingerprinting for school registration. I believe I’ve managed to get that stopped now, however this is not the case for many parents who are currently discovering that without their knowledge or consent their child’s biometrics have been taken by the school and stored for such trivial uses as borrowing a library book.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The companies involved in this technology keep stating there is no problem and parents have never objected…So thankfully a new web site has been launched which is now clearly stating for the record that this is clearly not the case.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Please check the web site out, and make your voice heard….&lt;a href="http://www.leavethemkidsalone.com/latest.htm"&gt;Leave Them Kids Alone&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115225883495108546?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115225883495108546/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115225883495108546' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115225883495108546'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115225883495108546'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/finger-printing-in-schools-just-gets.html' title='Finger printing in schools just gets hotter…'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115218128668993214</id><published>2006-07-06T11:19:00.000+01:00</published><updated>2006-07-06T11:22:11.913+01:00</updated><title type='text'>Custom Controls and Cross Threading</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;In .NET 2.0 a feature was introduced so as to raise an exception if an application attempted to access a Windows Control on a thread other than the thread in which the control was initially rendered. This is because Windows Controls are deemed not thread safe, and only expect to interact with a single thread, and thus have no state lock protection. In 1.1 you could blissfully ignore this and most of the time your code would work..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The feature in 2.0 is disabled by default, but when you run under the debugger it is enabled. The debugging environment sets the static member on the Control class &lt;strong&gt;CheckForIllegalCrossThreadCalls&lt;/strong&gt; to true.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Whenever you attempt to get hold of the underlying Windows handle for the control this static member is first inspected and if it evaluates to true the &lt;strong&gt;InvokeRequired&lt;/strong&gt; method is invoked to see if you are indeed on the correct thread. If you are not on the correct thread the exception is thrown&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The code below was generated by Reflector, taken from the base Control class&lt;br /&gt;&lt;/p&gt;&lt;span style="font-family:Lucida Console;font-size:8;"&gt;&lt;p&gt;public IntPtr get_Handle()&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if ((Control.checkForIllegalCrossThreadCalls &amp;amp;&amp; !Control.inCrossThreadSafeCall) &amp;amp;amp;&amp; this.InvokeRequired)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;throw new InvalidOperationException(SR.GetString("IllegalCrossThreadCall",&lt;br /&gt;&lt;/p&gt;&lt;p&gt;new object[] { this.Name }));&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if (!this.IsHandleCreated)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;this.CreateHandle();&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;return this.HandleInternal;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;There is a slight extra piece of complication in that it is possible to have some control operations that are thread safe, these calls use a class called Control.MultithreadSafeCalllScope which implements IDisposable as a way to wrapup blocks of code that are in fact thread safe and still need to have access to the underlying windows handle.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So using Reflectors Analyze feature I decided to see where this class was used in the framework so that you can see what Windows control methods are Thread safe…&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The results were as follows&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        &lt;span style="font-family:Lucida Console;font-size:8;"&gt;System.Windows.Forms.Control.BeginInvoke(Delegate, Object[]) : IAsyncResult&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:Lucida Console;font-size:8;"&gt;&lt;p&gt;        System.Windows.Forms.Control.CreateGraphics() : Graphics&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        System.Windows.Forms.Control.EndInvoke(IAsyncResult) : Object&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        System.Windows.Forms.Control.get_InvokeRequired() : Boolean&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        System.Windows.Forms.Control.get_WindowText() : String&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        System.Windows.Forms.Control.Invalidate(Boolean) : Void&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        System.Windows.Forms.Control.Invalidate(Rectangle, Boolean) : Void&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        System.Windows.Forms.Control.Invalidate(Region, Boolean) : Void&lt;br /&gt;&lt;/p&gt;&lt;p&gt;        System.Windows.Forms.Control.Invoke(Delegate, Object[]) : Object&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;A few posts back I saw that Invalidate was possible, but now I can see that I can also get the text associated with a windows control.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Anyway back to the plot….the reason for all this was to make my own custom controls behave the same as the underlying windows controls. I basically wanted to ensure that my control was only ever interacted with on a single thread. Since with UI apps you generally expect everything to happen on the main UI thread you don’t want to put the overhead of locking etc in as the majority of cases everything is happening on the UI thread.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So I’ve added a new method to my control called &lt;strong&gt;CheckForIllegalCrossCall &lt;/strong&gt;I make a call to this method inside each of my properties..&lt;br /&gt;&lt;/p&gt;&lt;span style="font-family:Lucida Console;font-size:8;"&gt;&lt;p&gt;private void CheckForIllegalCrossCall()&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if ((Control.CheckForIllegalCrossThreadCalls) &amp;amp;&amp; (InvokeRequired))&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;throw new InvalidOperationException("Illegal cross Thread operation");&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;Now I don’t need to worry about state corruption as state can now only be manipulated on a single thread. When debugging we will make the call to InvokeRequired and when not we will simply assume that the programmer knows what he’s doing…&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115218128668993214?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115218128668993214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115218128668993214' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115218128668993214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115218128668993214'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/custom-controls-and-cross-_115218128668993214.html' title='Custom Controls and Cross Threading'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115200419857309673</id><published>2006-07-04T10:07:00.000+01:00</published><updated>2006-07-04T10:09:58.656+01:00</updated><title type='text'>Last two weeks</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Last two weeks been very manic….went up to Edinburgh to deliver a course at the Edinburgh training centre.  Didn’t get to see much of the city but will certainly go back for a weekend visit, what I did see was pretty spectacular.  What was great was the fact that although you were in the city you could still get to see some pretty amazing “Vista’s”… ( wow that word is now so much in my vocabulary now ).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Second week doing a gig for MS Academic Insight were I spoke to nearly 50 academics on the wonders and joys of .NET.  Had a lot of fun and the hotel was fantastic.  More often and not Im in London hotels and going to a rural hotel was a breath of fresh air, the staff spoke English ok in this case with a Brummie dialect but that’s ok Im a Brummie too.  There were extremely helpful, and just little touches like Breakfast cooked to order goes a long way…A fellow speaker felt the need to praise the hotel on his blog too ( &lt;a href="http://www.robmiles.com/"&gt;http://www.robmiles.com/&lt;/a&gt; ), mainly for the in room tea tray.  The hotel was the Stourport Manor Hotel&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Rob was there to deliver a talk on Windows Mobile, and I must say things have come on along way since my original IPaq and NSBasic.  I can now develop using full loaded Visual Studio and .NET code…Rob was very passionate about Mobile, mainly due to richness in applications that you can now develop. Since in the case of a smart phone you have access to camera, blue tooth, phone  GPS, and GPRS/3G ( Internet ).  Such a vast array of devices compact and mobile…&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;He demo’d a neat space invaders game were you can take a picture of your co-worker and then use that picture as the evil alien and blaster them to smithereens… The funniest app was the SMS Roulette were game would select a random name from your contacts and then a random greeting be it nice or bad and send it….A great pub game as Rob put it…&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;So this was indeed neat you had full access to all the resources on the phone…After the initial laughter of this app, it got me and at least one other delegate thinking.. At no point did we get a warning from the app saying it was about to use the SMS service it just did…So the application spent my money without actually asking me…What else could it do…could it farm my contact list and email it to evilspammers.com..Who knows…&lt;br /&gt;&lt;/p&gt;&lt;p&gt;When I asked the question about security, there is a step you need to go through to get your app onto a phone whereby you need to get it signed by someone like Orange.  However they don’t see what the app does, they simply confirm that you are supplier.  It would seem to me that MS has missed the boat here again on security, I will feel very nervous about running smart  phone apps unless I can sandbox them.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;For example it would seem to me that the first time an app is installed its permissions should be restricted to CAS level  “internet zone” .  If it wishes to elevate permissions to do such things as SMS I should get a list of services I will be happy to grant to it.  For example SMS, and potentially to which number.  Thankfully they did see the security issue with the camera and managed code cannot access the camera, it can only load a picture from the store..So at least some one was awake at Redmond for the 5 minute mobile security meeting.   Come on MS you have made manage code have the ability to be so much more secure please use it….. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Rant over…..After seeing it though I want one…so I’m going to order a smart phone ASAP….I have a feeling that one of the  next killer apps will live on a smart phone…&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115200419857309673?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115200419857309673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115200419857309673' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115200419857309673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115200419857309673'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/last-two-weeks.html' title='Last two weeks'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115195203910309605</id><published>2006-07-03T19:38:00.000+01:00</published><updated>2006-07-03T19:40:39.106+01:00</updated><title type='text'>Another Security Rant</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;A while back I started playing with the managed support for secure stream protocols available for windows.  The managed wrappers of NegotiateStream wrap up access to SSPI.   In a previous post on my previous blog (&lt;a href="http://beaconsoft.co.uk/plog/index.php?op=ViewArticle&amp;amp;articleId=12&amp;amp;blogId=2"&gt;Previous Rant&lt;/a&gt;) I mentioned that even though you asked for a secure stream to be mutually authenticated, windows could decide not to bother and use NTLM and only send your credentials.  Personally I felt that  the API should have thrown an exception since it did not do what was said on the tin…Having discussed it with others it was pointed out that there is a property you can check on the stream called &lt;em&gt;IsMutuallyAuthenticated &lt;/em&gt;prior to actually using the stream, so not too bad..Assuming you remember to check..A little internal wrapper method and you could keep yourself safe.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;NegotiateStream is used as a foundation building block for higher level communication abstractions such as remoting.  When I use .NET remoting I have no access to the underlying stream I simply make a method call in the same way as I make a local call, the communication context is hidden from me.  So if in my remoting configuration I actually specify I want to use mutual authentication and it fails to achieve it because the other end refuses to play ball it falls back to NTLM and I’m none the wiser.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;One reason for opting for mutual authentication was the fact that the information Im sending to the server is for its eyes only, it may be sensitive and I don’t want it consumed by any other party.   Personally I find this totally unacceptable….&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So from a pure security point of view  that may rule out .NET remoting which would be a real shame, since I really don’t want to go back to the days of creating my own wire format for RPC between my client and server.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So this got me thinking if there was some kind of workaround.  The strategy that I think you can adopt is the following &lt;br /&gt;&lt;/p&gt;&lt;p&gt;On the server, declare your remoting service in the normal way, and in addition provide a simple tcp listener on a well known port.  This tcp listener is  the real trusted entity,  clients should negotiate a stream to the listener using mutual authentication and after establishing it check that it was successful..  The server sends back along the  stream the URL for the remoting service.  The client then uses the contained URL to connect back to host..&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This way the client can  be sure of using mutual authentication to validate the service, after the service has been validated the client continues to use RPC based protocols.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115195203910309605?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115195203910309605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115195203910309605' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195203910309605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195203910309605'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/another-security-rant.html' title='Another Security Rant'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115195200627104334</id><published>2006-07-03T19:37:00.000+01:00</published><updated>2006-07-03T19:40:06.286+01:00</updated><title type='text'>At least one more Thread Safe Method on Windows Controls</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Its been long understood that it is unsafe to call methods and properties on Windows controls unless you are on the same thread that created the control.   Windows controls have always been designed with single threaded environment in mind.  In .NET 1.1 you could actually perform the operations and on the whole things did seem to work, until perhaps the application is deployed and then it breaks….Thankfully in 2.0 MS have added programmatic protection when the your application is connected to a debugger, and will fire  an InvalidOperationException.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;To work around this issue you can deploy the standard InvokeRequired pattern, were by you call InvokeRequired method on the control you wish to access and if that returns true call BeginInvoke on the control  passing it a delegate instance that represents the work you wish to have carried out on the controls owning thread.  Hold on you said you can’t access a control unless you are on its owning thread, that’s true in the whole accept for some select methods&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;div&gt;InvokeRequired&lt;br /&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;BeginInvoke&lt;br /&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;Invoke&lt;br /&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;CreateGraphics&lt;br /&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The above list was my understanding before today, but what I realised today was that another method can be added to the list.  This holy method is Invalidate… I stumbled upon this whilst creating a more funky progress bar control.  The control had a progress property that was being set by my background task, and once set called invalidate In order for the progress bar to be updated, this produced no exception when the invalidate was called from the non owning thread, leading me to conclude that it is perfectly safe to do so….&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Which makes sense when you think about it since all it is doing is telling the OS that it needs to generate a Paint event for a given control, which ultimately will be delivered on the message queue for that controls owning thread.  Since there is no underlying control interaction on the non UI thread no exception is raised.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115195200627104334?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115195200627104334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115195200627104334' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195200627104334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195200627104334'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/at-least-one-more-thread-safe-method.html' title='At least one more Thread Safe Method on Windows Controls'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115195194451130913</id><published>2006-07-03T19:36:00.001+01:00</published><updated>2006-07-03T19:39:04.516+01:00</updated><title type='text'>Delegate binding in .NET 2</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;In .NET 1.1 a delegate defined like &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console"&gt;delegate void Proc(string foo);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Could only be instantiated with a method which had that exact signature.   In .NET 2.0 they relaxed it so that a method defined as&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console"&gt;void MyProc( object bar );&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Could be wrapped by the above delegate, since MyProc parameter is more restrictive, which makes sense.However what you can't do is&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console"&gt;delegate void Proc(int foo);&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;And make it wrap up&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console"&gt;void MyProc(object bar );&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The compiler will not let you...Hold on, int ultimately derives from System.Object so why not.  My guess is that it comes down to boxing, since in order to make code work the method MyProc must see a reference type.  The code invoking the delegate, or the CLR generated code  would have to be smart enough to see that the actual implementation was expecting a reference type and perform a boxing operation on the parameters being passed.   So perhaps the seamless type system is starting to show a few cracks....&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115195194451130913?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115195194451130913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115195194451130913' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195194451130913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195194451130913'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/delegate-binding-in-net-2.html' title='Delegate binding in .NET 2'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115195192068688729</id><published>2006-07-03T19:36:00.000+01:00</published><updated>2006-07-03T19:38:40.693+01:00</updated><title type='text'>NegotiateStream or is that bend over and take what’s given</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Been playing around with NegotiateStream, this class allows you to wrap up any other type of stream typically a socket stream with a tunnel.    As part of the tunnel setup you specify the source credentials and the destination identity.  The source credentials are used by the server to validate who you are and the destination identity is used in order to confirm that the server is who it says it is.  The first phase of setting up the tunnel is authentication, and Windows supports two types NTLM and Kerberos.  NTLM is not capable of performing mutual authentication so only cares about the client credentials.  Where as Kerberos does support both and will validate that the remote end is infact who you think it should be.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;So great in environments where it is important to know what’s on the other end of the wire, you need to use Kerberos, but here\'s the rub you would think that if you made a call as below, that it would enforce the use of Kerberos&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;span style="font-family:Lucida Console"&gt;&lt;p&gt;NegotiateStream s = new NegotiateStream&lt;br /&gt;&lt;/p&gt;&lt;p&gt;s.AuthenticateClient( CredentialCache.DefaultCredentials , “RemoteServiceUser” );&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;However if the RemoteServiceUser was unknown by Windows AD you would think that it would reject the call, but oh no it simply fails back to NTLM.  The only way you know it’s not done mutual authentication is when you check the s.IsMutuallyAuthenticated flag.  In my mind I think there needs to be an additional methods, one that specifies the remote identity and one that doesn't.  That way it’s clear that I want or don\'t want mutual authentication...If I want it and it doesn't happen then an exception needs to be thrown, I shouldn't have to check a property on the stream after the fact, and worse still if I don't want it I shouldn't have to specify anything not even String.Empty.&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115195192068688729?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115195192068688729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115195192068688729' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195192068688729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195192068688729'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/negotiatestream-or-is-that-bend-over.html' title='NegotiateStream or is that bend over and take what’s given'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115195185163450489</id><published>2006-07-03T19:35:00.001+01:00</published><updated>2006-07-03T19:37:31.636+01:00</updated><title type='text'>Fingerprinting in schools</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;I’ve been campaigning in my kids school to stop the introduction of finger printing for school registration.Â  I was interviewed by the Guardian on Tuesday, the article can be &lt;a href="http://technology.guardian.co.uk/weekly/story/0,,1742091,00.html"&gt;found&lt;/a&gt; here&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115195185163450489?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115195185163450489/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115195185163450489' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195185163450489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195185163450489'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/fingerprinting-in-schools.html' title='Fingerprinting in schools'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115195183451982476</id><published>2006-07-03T19:35:00.000+01:00</published><updated>2006-07-03T19:37:14.523+01:00</updated><title type='text'>.NET Generics and C++ STL</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;A fellow instructor was commenting, well moaning to be exact about the fact that .NET generics were not as flexible as C++ templates.  In this particular case he wanted to produce a generic Complex number type, such that he could write a single version and instantiate it for ints, doubles etc.  This is trivial in C++ templates, but not so in .NET.  I did manage to get something close C++ templates in terms of functionality, the details are too long for my primitive blogging editor so Ive written up my findings &lt;a href="http://www.beaconsoft.co.uk/Articles/generics.html"&gt;here&lt;/a&gt; .  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Whilst undertaking this task there is a feature I would really like from the C# compiler and that is a pragma to turn auto boxing off.  Why well  when writing code that you wish to tune to death, such as a generic algorithm it would be nice to be told at compile time that boxing will be occurring.  I guess I could write a generic unit test that inspects a method and fails if it finds a boxing op code&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115195183451982476?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115195183451982476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115195183451982476' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195183451982476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195183451982476'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/net-generics-and-c-stl.html' title='.NET Generics and C++ STL'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115195181636047787</id><published>2006-07-03T19:34:00.001+01:00</published><updated>2006-07-03T19:36:56.366+01:00</updated><title type='text'>.NET Generics and static methods</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;Been playing around with generics a bit more and have discovered something a little strange. When you run it you will see that you get the same result even though you instantiate the generic method with two different types that have the opposite functionality.   If you know how generics work under the covers then I guess you will think I wouldn\'t be that stupid to write the code below, but If you are not completely up to speed with how it is implemented in the CLR then you may think the behaviour below is a little strange.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;span style="font-family:Lucida Console"&gt;&lt;p&gt;using System.Collections.Generic;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;using System.Text;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;namespace Constraints&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;public class A&lt;br /&gt;&lt;/p&gt;&lt;p&gt; {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;public static bool operator ==(A lhs, A rhs)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{ return true; }&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;span style="font-family:Lucida Console"&gt;&lt;p&gt; public static bool operator !=(A lhs, A rhs)&lt;br /&gt;&lt;/p&gt;&lt;p&gt; { return false; }&lt;br /&gt;&lt;/p&gt;&lt;p&gt; }&lt;br /&gt;&lt;/p&gt;&lt;p&gt; public class B : A&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;public static bool operator ==(B lhs, B rhs)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{  return false;}&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;span style="font-family:Lucida Console"&gt;&lt;p&gt;public static bool operator !=(B lhs, B rhs)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{ return true; }&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;span style="font-family:Lucida Console"&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt; class Program&lt;br /&gt;&lt;/p&gt;&lt;p&gt; {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;   public static void PerformOperation&amp;lt;T&amp;gt;(T lhs , T rhs ) where T:A&lt;br /&gt;&lt;/p&gt;&lt;p&gt; {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;      if (lhs == rhs)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;       {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    Console.WriteLine(“Equal...”);&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  }&lt;br /&gt;&lt;/p&gt;&lt;p&gt;else&lt;br /&gt;&lt;/p&gt;&lt;p&gt; {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;    Console.WriteLine(“Not Equal...”)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;} &lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;static void Main(string[] args)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;      A v1 = new A();&lt;br /&gt;&lt;/p&gt;&lt;p&gt;A v2 = new A();&lt;br /&gt;&lt;/p&gt;&lt;p&gt;PerformOperation&amp;lt;A&amp;gt;(v1, v2);&lt;br /&gt;&lt;/p&gt;&lt;p&gt;B v3 = new B();&lt;br /&gt;&lt;/p&gt;&lt;p&gt;B v4 = new B();&lt;br /&gt;&lt;/p&gt;&lt;p&gt;PerformOperation&amp;lt;B&amp;gt;(v3, v4);&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt; In fact the C# compiler tries to stop you falling into this trap with a generic method with no constraints.  The code below will not compile, the reason being the way in which genercis have been implemented.  In .NET a generic method or type are constructed using common piece of IL using special generic IL instructions.  All it needs to be know at compile time is which method to call to perform a piece of functionality, the binding to the final implementation either happens at JIT time for valuetypes or using runtime polymorphism in the case of ref types.  For static methods and non virtual methods the binding happens when the generic method or type is compiled only the correct specific behaviour is used if the methods are polymorphic, or you supply the same type as defined by the constraint and not a more specialised version.  It is for this reason that the C# compiler will not compile the code below as it will always perform an object comparison ( E.g. Reference equality ) even if the method is called PerformOperation&amp;lt;string&amp;gt;( string1 , string2)&lt;br /&gt;&lt;/p&gt;&lt;span style="font-family:Lucida Console"&gt;&lt;p&gt;public static void PerformOperation&amp;lt;T&amp;gt;(T lhs , T rhs )&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;   if (lhs == rhs)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;   {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Console.WriteLine(“Equal...”);&lt;br /&gt;&lt;/p&gt;&lt;p&gt;   }&lt;br /&gt;&lt;/p&gt;&lt;p&gt;   else&lt;br /&gt;&lt;/p&gt;&lt;p&gt;{&lt;br /&gt;&lt;/p&gt;&lt;p&gt;  Console.WriteLine(“Not Equal...”;)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;p&gt;What I’m failing to understand is why in my case it allows the compilation since it basically suffers the same issue.  Perhaps generic methods should not be allowed to use non polymorphic methods.&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115195181636047787?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115195181636047787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115195181636047787' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195181636047787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195181636047787'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/net-generics-and-static-methods.html' title='.NET Generics and static methods'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30604582.post-115195179210241652</id><published>2006-07-03T19:34:00.000+01:00</published><updated>2006-07-03T19:36:32.106+01:00</updated><title type='text'>ASP.NET Themes</title><content type='html'>&lt;span xmlns=""&gt;&lt;p&gt;The new theme support in ASP.NET is pretty cool.  Although personally I don\'t think they took it far enough.  When you design your page you can add an attribute to the @Page tag that states which theme to use when rendering this page, this gives the web site designer some flexibility in that they can change the look and feel of the site with a simple change. The simplest way to do this is with a single global change in the &lt;strong&gt;web.config&lt;/strong&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&amp;lt;configuration xmlns=&lt;a href="http://schemas.microsoft.com/.NetConfiguration/v2.0"&gt;http://schemas.microsoft.com/.NetConfiguration/v2.0&lt;/a&gt;&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;lt;system&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&amp;lt;pages theme=”MyTheme&amp;amp;quot”/&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;lt;/system&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;For me though the cool thing about themes is to allow the user of the web site to select the theme they would like to use.  As far as I can tell there is no direct support in ASP.NET to do this for you. So I set about writing a component that could do this.  So what we need to do is.  For each page as it is about to be rendered change the theme used for that page select the theme based on the user preferred theme&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;In order to intercept the rendering of each page at the appropriate point you can provide a handler for the Page PreInit event, inside this handler you can add the appropriate code to change the theme to use for just that page. In order to hook up to this event I decided on a design where if you wanted a page to have the user selected theme then instead of creating a WebForm that derives from System.Web.UI.Page you actually derive from my new UserThemedPage type which ultimately derives from System.Web.UI.Page.  This can be simply done inside the forms Code view, Inside the constructor for UserThemedPage I add the necessary event registration code. Thus when the WebForm  is created the code Â is in place to handle the PreInit event and apply some policy to determine what theme to actually use.  For the second part we need to provide a way for the user to select a theme and also for the theme to be retained across multiple pages and hopefully multiple visits to the site. I didn’t really want to introduce the need for non anonymous access and store the users preferences in a database, so I opted for the use of cookies to store the user\'s prefered theme.   Since not every user wishes to enable cookies, I also opted to store the theme in the session store allowing users to retain their preferred theme for the duration of the session, but would need to reselect it on re-entering the site.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;As for selecting the theme to use, I did not want to provide the actual UI for this but simply a method that would allow simple iteration of possible themes to use and then a simple set/get property interface for setting the chosen theme.  The iterator simply returns the set of themes that are defined for the current application, its then up to the chosen web app to decide how to ask the user for their chosen theme.  So now in order to have a user select their own theme and have it persist across multiple pages and visits, you simply need to derive from my UserThemedPage as opposed to System.Web.UI.Page and provide a form to select the chosen theme.  Trivial...You can download the component source and example from the &lt;a href="http://www.beaconsoft.co.uk/download.html"&gt;Download Page&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30604582-115195179210241652?l=andyclymer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyclymer.blogspot.com/feeds/115195179210241652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30604582&amp;postID=115195179210241652' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195179210241652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30604582/posts/default/115195179210241652'/><link rel='alternate' type='text/html' href='http://andyclymer.blogspot.com/2006/07/aspnet-themes.html' title='ASP.NET Themes'/><author><name>Andy Clymer</name><uri>http://www.blogger.com/profile/06656714961652398263</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://photos1.blogger.com/blogger/803/3286/1600/Me2Reduced.jpg'/></author><thr:total>0</thr:total></entry></feed>
