<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Dario Airoldi TechNotes</title><link>http://blogs.msdn.com/darioa/default.aspx</link><description /><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Key reasons why use WPF on a Business Application</title><link>http://blogs.msdn.com/darioa/archive/2009/01/03/key-reasons-why-use-wpf-on-a-business-application.aspx</link><pubDate>Sat, 03 Jan 2009 02:00:52 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9269815</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/darioa/comments/9269815.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=9269815</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=9269815</wfw:comment><description>For some time, there has been discussion on whether WPF may be a good choice for writing Business Applications. Typical reasons against using it are that Business Applications do not require graphic capabilities , WPF is quite a new technology, it requires...(&lt;a href="http://blogs.msdn.com/darioa/archive/2009/01/03/key-reasons-why-use-wpf-on-a-business-application.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9269815" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/darioa/archive/tags/Framework/default.aspx">Framework</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows/default.aspx">Windows</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows+Vista/default.aspx">Windows Vista</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Framework+3/default.aspx">Framework 3</category><category domain="http://blogs.msdn.com/darioa/archive/tags/VistaLogo/default.aspx">VistaLogo</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows+Presentation+Foundation+-+WPF/default.aspx">Windows Presentation Foundation - WPF</category></item><item><title>Micro Framework TripComputer Sample</title><link>http://blogs.msdn.com/darioa/archive/2007/04/25/micro-framework-tripcomputer-sample.aspx</link><pubDate>Wed, 25 Apr 2007 22:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2275364</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/darioa/comments/2275364.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=2275364</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=2275364</wfw:comment><description>Micro Framework introduces a new approach to embedded development. The following key points: Minimal hardware requirements Strong runtime support Easy and intuitive development model An extensible emulation environment Make it easy to address application...(&lt;a href="http://blogs.msdn.com/darioa/archive/2007/04/25/micro-framework-tripcomputer-sample.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2275364" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/darioa/attachment/2275364.ashx" length="1050245" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/darioa/archive/tags/Framework/default.aspx">Framework</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Framework+3/default.aspx">Framework 3</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows+Presentation+Foundation+-+WPF/default.aspx">Windows Presentation Foundation - WPF</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Micro+Framework/default.aspx">Micro Framework</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows+Embedded/default.aspx">Windows Embedded</category></item><item><title>WCF Samples</title><link>http://blogs.msdn.com/darioa/archive/2007/03/25/wcf-samples.aspx</link><pubDate>Sun, 25 Mar 2007 20:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1947910</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/darioa/comments/1947910.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=1947910</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=1947910</wfw:comment><description>Windows Communication Foundation (WCF) the new API set and runtime for message based communication. WCF replaces old web services as WCF Services support HTTP/Soap based communication. In particular, WCF now supports WS* standards for secure, reliable...(&lt;a href="http://blogs.msdn.com/darioa/archive/2007/03/25/wcf-samples.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1947910" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/darioa/attachment/1947910.ashx" length="1227993" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/darioa/archive/tags/Framework/default.aspx">Framework</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows+Vista/default.aspx">Windows Vista</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Framework+3/default.aspx">Framework 3</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows+Communication+Foundation+-+WCF/default.aspx">Windows Communication Foundation - WCF</category></item><item><title>"Certified for Vista" Logo Samples</title><link>http://blogs.msdn.com/darioa/archive/2007/01/11/certified-for-vista-logo-samples.aspx</link><pubDate>Thu, 11 Jan 2007 17:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1450720</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/darioa/comments/1450720.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=1450720</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=1450720</wfw:comment><description>The following samples show the most common tasks you may need to perform on your application to get the "Certified for Vista Logo". In particular, CertifiedforVistaSamples.zip include: Manifestsample : shows how to apply a manifest to your .Net application...(&lt;a href="http://blogs.msdn.com/darioa/archive/2007/01/11/certified-for-vista-logo-samples.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1450720" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/darioa/attachment/1450720.ashx" length="265429" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows/default.aspx">Windows</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows+Vista/default.aspx">Windows Vista</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Framework+3/default.aspx">Framework 3</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Certified+for+Vista/default.aspx">Certified for Vista</category><category domain="http://blogs.msdn.com/darioa/archive/tags/VistaLogo/default.aspx">VistaLogo</category></item><item><title>Steps to prepare lab machines with Windows Vista AIK</title><link>http://blogs.msdn.com/darioa/archive/2007/01/10/steps-to-prepare-lab-machines-with-windows-vista-aik.aspx</link><pubDate>Wed, 10 Jan 2007 21:02:52 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1445361</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/darioa/comments/1445361.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=1445361</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=1445361</wfw:comment><description>The steps to create a lab installation are easy with Windows Vista AIK. With a clear idea of what you need to install on the machines and the requirements described below, a couple of days may be enough to have everything in place. Also, only a single...(&lt;a href="http://blogs.msdn.com/darioa/archive/2007/01/10/steps-to-prepare-lab-machines-with-windows-vista-aik.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1445361" width="1" height="1"&gt;</description></item><item><title>Steps to create a bootable Windows PE RAM CD/DVD</title><link>http://blogs.msdn.com/darioa/archive/2007/01/10/steps-to-create-a-bootable-windows-pe-ram-cd-dvd.aspx</link><pubDate>Wed, 10 Jan 2007 21:01:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1445356</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/darioa/comments/1445356.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=1445356</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=1445356</wfw:comment><description>The following article shows how to create a bootable WinPE disk with Windows Vista Automated Installation Kit (WAIK) . Requirements WAIK : Windows Vista Automated Installation Kit (get the download here ). CDBurn/Dvdburn utility: this tool allows burning...(&lt;a href="http://blogs.msdn.com/darioa/archive/2007/01/10/steps-to-create-a-bootable-windows-pe-ram-cd-dvd.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1445356" width="1" height="1"&gt;</description></item><item><title>Steps to Create an Unattended Setup for Windows Vista</title><link>http://blogs.msdn.com/darioa/archive/2007/01/10/steps-to-create-an-unattended-setup-for-windows-vista.aspx</link><pubDate>Wed, 10 Jan 2007 20:57:55 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1445349</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/darioa/comments/1445349.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=1445349</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=1445349</wfw:comment><description>The following article shows how to create an automated setup per windows Vista using Windows Vista Automated Installation Kit (WAIK) . Requirements Vista DVD : a DVD with Windows Vista. WAIK : Windows Vista Automated Installation Kit (get the download...(&lt;a href="http://blogs.msdn.com/darioa/archive/2007/01/10/steps-to-create-an-unattended-setup-for-windows-vista.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1445349" width="1" height="1"&gt;</description></item><item><title>Frequently asked questions on Windows Vista compatibility and Certification Logos</title><link>http://blogs.msdn.com/darioa/archive/2006/11/29/faq-on-windows-vista-compatibility-and-certification.aspx</link><pubDate>Wed, 29 Nov 2006 16:06:02 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1171280</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/darioa/comments/1171280.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=1171280</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=1171280</wfw:comment><description>The following article proposes some Frequently Asked Questions and Answers about Windows Vista Compatibility and Vista Certification Logos. I gathered information below from compatibility and logo draft documents and from internet resources that are subject...(&lt;a href="http://blogs.msdn.com/darioa/archive/2006/11/29/faq-on-windows-vista-compatibility-and-certification.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1171280" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows/default.aspx">Windows</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Windows+Vista/default.aspx">Windows Vista</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Framework+3/default.aspx">Framework 3</category><category domain="http://blogs.msdn.com/darioa/archive/tags/Certified+for+Vista/default.aspx">Certified for Vista</category><category domain="http://blogs.msdn.com/darioa/archive/tags/VistaLogo/default.aspx">VistaLogo</category></item><item><title>Write your services leveraging existing thread pool technologies</title><link>http://blogs.msdn.com/darioa/archive/2006/09/15/Write-your-services-leveraging-existing-thread-pool-technologies.aspx</link><pubDate>Fri, 15 Sep 2006 15:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:755823</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/darioa/comments/755823.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=755823</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=755823</wfw:comment><description>&lt;p&gt;here is an idea on how to write your services leveraging the power of existing thread pool technologies. 
&lt;/p&gt;&lt;p&gt;Thread pooling is important for scalability. &lt;br/&gt;Pooling algorithms generally include complex logic for self tuning, queuing incoming requests, etc. &lt;br/&gt;These are some of the reasons why I'd rather not bother writing thread pooling code in my services and leverage existing technologies instead. 
&lt;/p&gt;&lt;p&gt;In this article I provide a sample code for a service to receive messages from a MSMQ queue and process them by means of the ASPNet Thread Pool. &lt;br/&gt;Similar code can be written to receive commands from a socket or some other source. 
&lt;/p&gt;&lt;p&gt;The code is divided into 3 sections: 
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;WAITING SECTION&lt;/em&gt;&lt;/strong&gt; (&lt;em&gt;PeekWorkItem()&lt;/em&gt; method): this section is used to enter wait mode ('&lt;strong&gt;&lt;em&gt;peek mode&lt;/em&gt;&lt;/strong&gt;') on the resource (the queue). Only one thread is allowed to enter 'peek mode' to avoid too many callbacks when a new message arrives. 'peek mode' is represented by flag &lt;em&gt;_nIsPeekActive&lt;/em&gt; which is protected against concurrency. &lt;br/&gt;In case of exceptions (es. because of MSMQ service down) a new PeekWorkItem() is submitted with a delay to avoid 100% CPU loops on error conditions. 
&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;WAKE UP SECTION&lt;/em&gt;&lt;/strong&gt; (&lt;em&gt;PeekCompleted()&lt;/em&gt; method): this section is run when a new message arrives on the queue. In this section a number of requests are submitted to the thread pool to read messages from the queue and process them. &lt;br/&gt;The code keeps count of the number of requests submitted to the thread pool (into variable &lt;em&gt;_nReceiveCount&lt;/em&gt;). It is the thread pool choice to really process those requests concurrently or to serve them in a more scattered way. In case of exceptions (es. because of MSMQ service down) a new PeekWorkItem() is submitted with a delay to avoid 100% CPU loops on error conditions. 
&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;RECEIVE SECTION&lt;/em&gt;&lt;/strong&gt; (&lt;em&gt;ReceiveWorkItem()&lt;/em&gt; method): this section is the work item run by the thread pool that reads messages from the queue and process them. &lt;br/&gt;Code sections run on a thread pool should never be 'too short' or 'too long' as that may waste resources. So, ReceiveWorkItem() is designed to read and process as many messages as possible up to a configurable timeout (or the queue becomes empty). 
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src="http://darioawinisp.members.winisp.net/091506_1416_Write%20your%201.png" alt="" height="316" width="695"/&gt;&lt;span style="color:#4f81bd; font-size:9pt"&gt;&lt;strong&gt;
			&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#4f81bd; font-size:9pt"&gt;&lt;strong&gt;Figure 1: MSMQ Custom Listener engine &lt;/strong&gt;&lt;/span&gt;
	&lt;/p&gt;&lt;h1&gt;WAITING SECTION (PeekWorkItem() method) 
&lt;/h1&gt;&lt;p&gt;IO mechanisms generally provide asynchronous ways of receiving data.&lt;br/&gt;This saves the need of creating threads just to wait on them.&lt;br/&gt;In facts, there are cheaper ways to wait on empty resources, which are usually exposed as Asynchronous APIs.&lt;br/&gt;.Net MSMQ asynchronous API to read messages from a queue is &lt;em&gt;Queue.BeginPeek()&lt;/em&gt; method.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;&lt;em&gt;PeekWorkItem()&lt;/em&gt;&lt;/strong&gt; is the code section where my service calls &lt;em&gt;&lt;strong&gt;_queue.BeginPeek&lt;/strong&gt;()&lt;/em&gt; method to look for messages into the MSMQ queue.&lt;br/&gt;&lt;em&gt;_queue&lt;/em&gt; variable refers to the queue the service is looking for messages from.&lt;br/&gt;&lt;br/&gt;Before calling &lt;em&gt;_queue.BeginPeek()&lt;/em&gt;, &lt;em&gt;PeekWorkItem()&lt;/em&gt; sets flag &lt;em&gt;_nIsPeekActive&lt;/em&gt; to 1 (i.e. it enters '&lt;em&gt;Peek mode&lt;/em&gt;'). 
&lt;/p&gt;&lt;p&gt;&lt;em&gt;_nIsPeekActive&lt;/em&gt; flag keeps track that somebody is waiting on the queue and avoids other threads call &lt;em&gt;BeginPeek&lt;/em&gt;() on it.&lt;br/&gt;This reduces the number of callbacks that are processed when new messages arrive on the queue.&lt;br/&gt;  
&lt;/p&gt;&lt;p&gt;If &lt;em&gt;_queue&lt;/em&gt; is empty, &lt;em&gt;_queue.BeginPeek()&lt;/em&gt; doesn't block the calling thread.&lt;br/&gt;So, no thread objects are wasted waiting on empty queues and no threads are kept blocked for long time.&lt;br/&gt;That's why, &lt;em&gt;PeekWorkItem()&lt;/em&gt; may safely be run on thread pool threads.&lt;br/&gt;  
&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;#region&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; PeekWorkItem&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;///&lt;/span&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;
			&lt;/span&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;submits a BeginPeek() to the queue.&lt;/span&gt;&lt;span style="color:gray"&gt;&lt;span style="font-family:Lucida Console"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
			&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;///&lt;/span&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;
			&lt;/span&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;&amp;lt;remarks&amp;gt;&lt;/span&gt;&lt;span style="color:green"&gt;&lt;span style="font-family:Lucida Console"&gt;only one BeginPeek() may be active on the queue at any moment.&lt;/span&gt;
			&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;///&lt;/span&gt;&lt;span style="color:green"&gt;&lt;span style="font-family:Lucida Console"&gt; BeginPeek() invocation is protected by the synchronized flag 'IsPeekActive' which is set just before calling it and reset at the PeekCompleted() callback.&lt;/span&gt;
			&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;///&lt;/span&gt;&lt;span style="color:green; font-family:Lucida Console"&gt; In case BeginPeek fails (ex. because of invalid access or any other reason) 'IsPeekActive' is also reset and a delayed peek is submit to check whether it may succeed at a later time.&lt;/span&gt;&lt;span style="color:gray"&gt;&lt;span style="font-family:Lucida Console"&gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;
			&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;public&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt;
				&lt;span style="color:blue"&gt;void&lt;/span&gt;
				&lt;strong&gt;&lt;em&gt;PeekWorkItem()&lt;/em&gt;&lt;/strong&gt; {&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;try&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; {&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// Try a BeginPeek() on the queue; if _nIsPeekActive==1 somebody else is in peek mode, so, PeekWorkItem does nothing... &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;if&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; (Interlocked.CompareExchange(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _nIsPeekActive, 1, 0) == 0) { &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// Entering Peekmode: Only one thread is allowed to call BeginPeek() to prevent too many callbacks when a new message arrives &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;_queue.BeginPeek(MessageQueue.InfiniteTimeout, &lt;span style="color:blue"&gt;null&lt;/span&gt;, &lt;span style="color:blue"&gt;new&lt;/span&gt; AsyncCallback(PeekCompleted)); &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;}&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;} &lt;span style="color:blue"&gt;catch&lt;/span&gt; (Exception ex) { &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// Submit a delayed PeekWorkItem() and ignore the exception. &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// BeginPeek may fail when there are problems with the MSMQ service. &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// The new PeekWorkItem() is delayed to avoid an loop with 100% CPU in such case. &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;ICall call = &lt;span style="color:blue"&gt;new&lt;/span&gt; DelayedCall(&lt;span style="color:blue"&gt;new&lt;/span&gt; DelegateCall(&lt;span style="color:blue"&gt;new&lt;/span&gt; VoidEmptyArgsDelegate(PeekWorkItem)), _nPeekDelayOnException);&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// Release _nIsPeekActive flag: the next PeekWorkItem() will be allows to enter peekmode! &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;Interlocked.Exchange(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _nIsPeekActive, 0);&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// Start the delayed PeekWorkItem() and save the call object into '_call member'. &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// if '_call member' already contains a delayed call object dispose it to have only one active call object at a time &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;call.Invoke(); &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;IDisposable oldCall = Interlocked.Exchange&amp;lt;ICall&amp;gt;(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _call, call) &lt;span style="color:blue"&gt;as&lt;/span&gt; IDisposable; &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;if&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; (oldCall != &lt;span style="color:blue"&gt;null&lt;/span&gt;) { oldCall.Dispose(); }&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;}&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;}&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;#endregion &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;h1&gt;WAKE UP SECTION (PeekCompleted() method) 
&lt;/h1&gt;&lt;p&gt;The wake up section is run when new messages arrive on the queue (or, exceptional conditions happen waiting on it).&lt;br/&gt;In facts &lt;strong&gt;&lt;em&gt;PeekCompleted()&lt;/em&gt;&lt;/strong&gt; method was registered as a callback on the queue, in the 'waiting section', when calling &lt;em&gt;BeginPeek()&lt;/em&gt; method.&lt;br/&gt;Remember that only one thread is allowed to set &lt;em&gt;_nIsPeekActive&lt;/em&gt; flag and call &lt;em&gt;_queue.BeginPeek()&lt;/em&gt;.&lt;br/&gt;So, only one callback is run when messages arrive on the queue.&lt;br/&gt;&lt;br/&gt;Just after wake up, &lt;em&gt;PeekCompleted()&lt;/em&gt; calls &lt;em&gt;_queue.EndPeek()&lt;/em&gt; to check whether new messages are available on the queue. 
&lt;/p&gt;&lt;p&gt;If &lt;em&gt;_queue.EndPeek()&lt;/em&gt; succeeds, there are messages available so, &lt;em&gt;PeekCompleted() &lt;/em&gt;submits some requests for processing them (i.e. delegates to &lt;em&gt;ReceiveWorkItem()&lt;/em&gt;), to the thread pool.&lt;br/&gt;&lt;em&gt;PeekCompleted()&lt;/em&gt; doesn't use the message returned by &lt;em&gt;_queue.EndPeek()&lt;/em&gt;; in facts, it is the Receive section that chooses how to receive messages, whether to share the receive transaction with the message processing etc.&lt;br/&gt;&lt;br/&gt;&lt;em&gt;PeekCompleted()&lt;/em&gt; keeps count of the requests currently submitted to the thread pool by means of variable &lt;em&gt;_nReceiveCount&lt;/em&gt;.&lt;br/&gt;In facts, &lt;em&gt;PeekCompleted()&lt;/em&gt; increments &lt;em&gt;_nReceiveCount&lt;/em&gt; every time it submits a request for processing to the thread pool and, in turn, &lt;em&gt;_nReceiveCount&lt;/em&gt; is decremented every time a thread pool request completes.    
&lt;/p&gt;&lt;p&gt;&lt;em&gt;PeekCompleted()&lt;/em&gt; makes sure that requests for message processing are sent to the thread pool with &lt;em&gt;_nReceiveCount &lt;/em&gt;up to a configurable limit (held in variable &lt;em&gt;_nMaxConcurrency)&lt;/em&gt;.&lt;br/&gt;&lt;br/&gt;&lt;em&gt;PeekCompleted()&lt;/em&gt; releases &lt;span style="text-decoration:underline"&gt;always&lt;/span&gt;
		&lt;em&gt;_nIsPeekActive&lt;/em&gt; flag: it does that before sending the last request for processing or in the finally block.&lt;br/&gt;This allows a new thread enter 'peek mode', when the queue becomes empty or some receive work item complete for other reasons (e.g. by timeout).&lt;br/&gt;&lt;br/&gt;In case of exceptions there might be problems on the queue so (after releasing _nIsPeekActive flag) &lt;em&gt;PeekCompleted()&lt;/em&gt; submits a delayed request to &lt;em&gt;PeekWorkItem()&lt;/em&gt; (the waiting section).&lt;br/&gt;The delay is necessary to prevent a CPU overhead on the PeekWorkItem()/PeekCompleted() loop during the exceptional condition. 
&lt;/p&gt;&lt;p&gt;   
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;#region&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; PeekCompleted&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;///&lt;/span&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;
			&lt;/span&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;PeekCompleted is triggered when a BeginPeek() is active and any message is received by the queue.&lt;/span&gt;&lt;span style="color:gray"&gt;&lt;span style="font-family:Lucida Console"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
			&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;///&lt;/span&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;
			&lt;/span&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;&amp;lt;remarks&amp;gt;&lt;/span&gt;&lt;span style="color:green"&gt;&lt;span style="font-family:Lucida Console"&gt;PeekCompleted resets 'IsPeekActive' and submits an appropriate number of ReceiveWorkItems to the thread pool for receiving messages.&lt;/span&gt;
			&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;///&lt;/span&gt;&lt;span style="color:green"&gt;&lt;span style="font-family:Lucida Console"&gt; ReceiveWorkItems are submitted according to the concurrency configuration setting for the queue.&lt;/span&gt;
			&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:gray; font-family:Lucida Console"&gt;///&lt;/span&gt;&lt;span style="color:green; font-family:Lucida Console"&gt; currently active ReceiveWorkItems can be monitored by means of 'Requests Current' performance counter.&lt;/span&gt;&lt;span style="color:gray"&gt;&lt;span style="font-family:Lucida Console"&gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;
			&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;public&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt;
				&lt;span style="color:blue"&gt;void&lt;/span&gt;
				&lt;strong&gt;&lt;em&gt;PeekCompleted(IAsyncResult asyncResult)&lt;/em&gt;&lt;/strong&gt; {&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;bool&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; bPeekActiveReset = &lt;span style="color:blue"&gt;false&lt;/span&gt;;&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;try&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; {&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// any BeginPeek() must be matched with an EndPeek()... &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;Message msg = &lt;span style="color:blue"&gt;this&lt;/span&gt;._queue.EndPeek(asyncResult); &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// "Submits receive requests up to the maximun concurrency allowed; current ReceiveCount '_nReceiveCount', Max Concurrency '_nMaxConcurrency'." &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;int&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; nReceiveCount = Interlocked.CompareExchange(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _nReceiveCount, -1, -1); &lt;span style="color:green"&gt;// access to _nReceiveCount is sinchronized to allow &lt;/span&gt;&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;for&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; (; nReceiveCount &amp;lt; _nMaxConcurrency; ) {&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;nReceiveCount = Interlocked.Increment(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _nReceiveCount); &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;if&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; (nReceiveCount &amp;lt;= _nMaxConcurrency) {&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// "Releases the peekactive mode before sending the last ReceiveWorkItem()" &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;if&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; (nReceiveCount == _nMaxConcurrency) { Interlocked.Exchange(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _nIsPeekActive, 0); bPeekActiveReset = &lt;span style="color:blue"&gt;true&lt;/span&gt;; }&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;ThreadPool.QueueUserWorkItem(&lt;span style="color:blue"&gt;new&lt;/span&gt; WaitCallback(ReceiveWorkItem), &lt;span style="color:blue"&gt;this&lt;/span&gt;); &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;}&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;}&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;} &lt;span style="color:blue"&gt;catch&lt;/span&gt; (Exception ex) {&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:green; font-family:Lucida Console"&gt;// trace a warning and submits a delayed PeekWorkItem() in the finally block. &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;} &lt;span style="color:blue"&gt;finally&lt;/span&gt; {&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;if&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; (bPeekActiveReset == &lt;span style="color:blue"&gt;false&lt;/span&gt;) { &lt;span style="color:green"&gt;// Submits a delayed PeekWorkItem()&lt;/span&gt;&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;ICall call = &lt;span style="color:blue"&gt;new&lt;/span&gt; DelayedCall(&lt;span style="color:blue"&gt;new&lt;/span&gt; DelegateCall(&lt;span style="color:blue"&gt;new&lt;/span&gt; VoidEmptyArgsDelegate(PeekWorkItem)), _nPeekDelayOnException);&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;Interlocked.Exchange(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _nIsPeekActive, 0); &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;call.Invoke(); &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;IDisposable oldCall = Interlocked.Exchange&amp;lt;ICall&amp;gt;(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _call, call) &lt;span style="color:blue"&gt;as&lt;/span&gt; IDisposable; &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;if&lt;/span&gt;&lt;span style="font-family:Lucida Console"&gt; (oldCall != &lt;span style="color:blue"&gt;null&lt;/span&gt;) { oldCall.Dispose(); }&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;}&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;}&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="font-family:Lucida Console"&gt;}&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:9pt"&gt;&lt;span style="color:blue; font-family:Lucida Console"&gt;#endregion &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;   
 &lt;/p&gt;&lt;h1&gt;RECEIVE SECTION (ReceiveWorkItem() method) 
&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;ReceiveWorkItem()&lt;/em&gt;&lt;/strong&gt; is run on the thread pool to receive messages from the queue and process them.&lt;br/&gt;Code sections run on a thread pool should never be 'too short' or 'too long' as that may waste resources.&lt;br/&gt;For this reason &lt;em&gt;ReceiveWorkItem()&lt;/em&gt; is designed to process multiple messages up to a configurable time interval (&lt;em&gt;_nWorkItemTimeLimit&lt;/em&gt; variable) or the queue becomes empty.&lt;br/&gt;&lt;br/&gt;if the queue becomes empty, every running &lt;em&gt;ReceiveWorkItem()&lt;/em&gt; completes and (only) the last one processes a &lt;em&gt;PeekWorkItem()&lt;/em&gt; to enter '&lt;em&gt;Peek Mode&lt;/em&gt;' on the queue.&lt;br/&gt;Also, &lt;em&gt;PeekWorkItem() &lt;/em&gt;is processed when a &lt;em&gt;ReceiveWorkItem()&lt;/em&gt; completes because of &lt;em&gt;_nWorkItemTimeLimit &lt;/em&gt;expiration.&lt;br/&gt;if a &lt;em&gt;ReceiveWorkItem() &lt;/em&gt;completes because of an exception receiving or processing a message, the call to &lt;em&gt;PeekWorkItem() &lt;/em&gt;is delayed to limit CPU overhead in exceptional conditions.&lt;br/&gt;&lt;br/&gt;In case of failures processing a message, &lt;em&gt;ReceiveWorkItem() &lt;/em&gt;tries to save the failed message to a '_failedmessages' queue by means of &lt;em&gt;hlpSaveDeadMessage()&lt;/em&gt; method.&lt;br/&gt;&lt;br/&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;#region&lt;/span&gt; ReceiveWorkItem 
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:gray"&gt;///&lt;/span&gt;&lt;span style="color:green"&gt;
			&lt;/span&gt;&lt;span style="color:gray"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color:green"&gt;ReceiveWorkItem is processed on the thread pool to receive messages from the queue and process them.&lt;/span&gt;&lt;span style="color:gray"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:gray"&gt;///&lt;/span&gt;&lt;span style="color:green"&gt;
			&lt;/span&gt;&lt;span style="color:gray"&gt;&amp;lt;remarks&amp;gt;&lt;/span&gt;&lt;span style="color:green"&gt;ReceiveWorkItem retrieves messages according to the configuration and process them. &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:gray"&gt;///&lt;/span&gt;&lt;span style="color:green"&gt; in case of a processing failure a message, ReceiveWorkItem() tries to save the failed message to the '_failedmessages' queue. &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:gray"&gt;///&lt;/span&gt;&lt;span style="color:green"&gt; the move of the message to the failedmessages queue is performed with the same transactional settings used for retrieval from the original queue. in case of failure saving the message to the failedmessages queue the original message is restored to the original queue ONLY if the queue is configured for use of external transactions.&lt;/span&gt;&lt;span style="color:gray"&gt;&amp;lt;/remarks&amp;gt; &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;public&lt;/span&gt;
			&lt;span style="color:blue"&gt;void&lt;/span&gt;
			&lt;strong&gt;&lt;em&gt;ReceiveWorkItem(&lt;span style="color:blue"&gt;object&lt;/span&gt; oThis)&lt;/em&gt;&lt;/strong&gt; { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;int&lt;/span&gt; nReceiveCount = 0; &lt;span style="color:blue"&gt;bool&lt;/span&gt; bIsEmpty = &lt;span style="color:blue"&gt;false&lt;/span&gt;; &lt;span style="color:blue"&gt;bool&lt;/span&gt; bDelayPeekWorkItem = &lt;span style="color:blue"&gt;false&lt;/span&gt;; &lt;span style="color:blue"&gt;string&lt;/span&gt; sMessageId = &lt;span style="color:blue"&gt;null&lt;/span&gt;; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;try&lt;/span&gt; { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:green"&gt;// Receives a message from the queue '_queue' with transaction mode '_transactionType' (ReceiveCount: '_nReceiveCount') &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;DateTime dtExpiration = DateTime.MinValue; &lt;span style="color:blue"&gt;if&lt;/span&gt; (_nWorkItemTimeLimit &amp;gt;= 0) { dtExpiration = DateTime.Now.AddMilliseconds(_nWorkItemTimeLimit); } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;   
 &lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;for&lt;/span&gt; (&lt;span style="color:blue"&gt;bool&lt;/span&gt; bTimeLimitExceeded = &lt;span style="color:blue"&gt;false&lt;/span&gt;; bIsEmpty == &lt;span style="color:blue"&gt;false&lt;/span&gt; &amp;amp;&amp;amp; bTimeLimitExceeded == &lt;span style="color:blue"&gt;false&lt;/span&gt;; sMessageId = &lt;span style="color:blue"&gt;null&lt;/span&gt;) { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;Message oMessage = &lt;span style="color:blue"&gt;null&lt;/span&gt;; &lt;span style="color:blue"&gt;bool&lt;/span&gt; bIsReceiveCommitted = &lt;span style="color:blue"&gt;false&lt;/span&gt;; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;try&lt;/span&gt; { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:green"&gt;// creates a transaction scope for use of external transactions. A null transaction scope is used otherwise"); &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;TransactionScope oTransactionScope = (_transactionType == MessageQueueTransactionType.Automatic) ? &lt;span style="color:blue"&gt;new&lt;/span&gt; TransactionScope(TransactionScopeOption.RequiresNew) : &lt;span style="color:blue"&gt;null&lt;/span&gt;; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;using&lt;/span&gt; (oTransactionScope) { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 180pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;try&lt;/span&gt; { oMessage = _queue.Receive(TimeSpan.Zero, _transactionType); } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 180pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;catch&lt;/span&gt; (MessageQueueException tex) { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 216pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (tex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout) { bIsEmpty = &lt;span style="color:blue"&gt;true&lt;/span&gt;; } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 216pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;else&lt;/span&gt; { &lt;span style="color:blue"&gt;throw&lt;/span&gt;; } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 180pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 180pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (_transactionType != MessageQueueTransactionType.Automatic) { bIsReceiveCommitted = &lt;span style="color:blue"&gt;true&lt;/span&gt;; } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 180pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (oMessage != &lt;span style="color:blue"&gt;null&lt;/span&gt;) { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 216pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:green"&gt;// Processing message 'oMessage.Id' &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 216pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;sMessageId = oMessage.Id; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 216pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (_formatter != &lt;span style="color:blue"&gt;null&lt;/span&gt;) { oMessage.Formatter = _formatter; } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 216pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;ServiceMessage oServiceMessage = (ServiceMessage)oMessage.Body; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 216pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;ServiceMessage oRetMessage = hlpProcessMessage(oServiceMessage); 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 180pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 180pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (_transactionType == MessageQueueTransactionType.Automatic) { oTransactionScope.Complete(); } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} &lt;span style="color:blue"&gt;catch&lt;/span&gt; (Exception ex) { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (sMessageId == &lt;span style="color:blue"&gt;null&lt;/span&gt;) { &lt;span style="color:blue"&gt;throw&lt;/span&gt;
			&lt;span style="color:blue"&gt;new&lt;/span&gt; CommunicationEngineTargetException(&lt;span style="color:blue"&gt;string&lt;/span&gt;.Format(&lt;span style="color:maroon"&gt;"Exception '{0}' - '{1}' occurred receiving a message from queue '{2}' and the message ID could not be retrieved; the message cannot be saved to the deadqueue. If the queue is not configured with automatic transactions the message may be lost."&lt;/span&gt;, ex.GetType().Name, ex.Message, _queueConf.FormatName)); } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;bIsEmpty = hlpSaveDeadMessage(sMessageId, oMessage, &lt;span style="color:blue"&gt;ref&lt;/span&gt; bIsReceiveCommitted); 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (bIsReceiveCommitted == &lt;span style="color:blue"&gt;false&lt;/span&gt;) { bDelayPeekWorkItem = &lt;span style="color:blue"&gt;true&lt;/span&gt;; &lt;span style="color:blue"&gt;return&lt;/span&gt;; } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (_nWorkItemTimeLimit &amp;gt;= 0 &amp;amp;&amp;amp; dtExpiration &amp;lt;= DateTime.Now) { bTimeLimitExceeded = &lt;span style="color:blue"&gt;true&lt;/span&gt;; } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} &lt;span style="color:blue"&gt;catch&lt;/span&gt; (Exception ex) { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:green"&gt;// "Exception occurred receiving a message from queue '_queue'; message id is 'sMessageId' &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;bDelayPeekWorkItem = &lt;span style="color:blue"&gt;true&lt;/span&gt;; &lt;span style="color:green"&gt;// "Ignores the exception. and run finally block&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} &lt;span style="color:blue"&gt;finally&lt;/span&gt; { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;nReceiveCount = Interlocked.Decrement(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _nReceiveCount); 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;PublishEndRequestCounters(_queueConf); 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (!bIsEmpty || nReceiveCount == 0) { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (!bDelayPeekWorkItem) { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:green"&gt;// Submits a PeekWorkItem() &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;PeekWorkItem(); 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} &lt;span style="color:blue"&gt;else&lt;/span&gt;
			&lt;span style="color:blue"&gt;if&lt;/span&gt; (nReceiveCount == 0) { 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:green"&gt;// Submits a delayed PeekWorkItem() &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;ICall call = &lt;span style="color:blue"&gt;new&lt;/span&gt; DelayedCall(&lt;span style="color:blue"&gt;new&lt;/span&gt; DelegateCall(&lt;span style="color:blue"&gt;new&lt;/span&gt; VoidEmptyArgsDelegate(PeekWorkItem)), _nPeekDelayOnException); 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;call.Invoke(); 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;IDisposable oldCall = Interlocked.Exchange&amp;lt;ICall&amp;gt;(&lt;span style="color:blue"&gt;ref&lt;/span&gt; _call, call) &lt;span style="color:blue"&gt;as&lt;/span&gt; IDisposable; 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 144pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;if&lt;/span&gt; (oldCall != &lt;span style="color:blue"&gt;null&lt;/span&gt;) { oldCall.Dispose(); } 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 108pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 72pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} 
&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt"&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} 
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;} 
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Lucida Console; font-size:9pt"&gt;&lt;span style="color:blue"&gt;#endregion &lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;   &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=755823" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/darioa/attachment/755823.ashx" length="47905" type="image/jpeg" /></item><item><title>Queued Components vs MSMQ Triggers vs Custom Listeners</title><link>http://blogs.msdn.com/darioa/archive/2006/06/28/Queued-Components-vs-MSMQ-Triggers-vs-Custom-Listeners.aspx</link><pubDate>Wed, 28 Jun 2006 10:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:649415</guid><dc:creator>Dario Airoldi</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/darioa/comments/649415.aspx</comments><wfw:commentRss>http://blogs.msdn.com/darioa/commentrss.aspx?PostID=649415</wfw:commentRss><wfw:comment>http://blogs.msdn.com/darioa/rsscomments.aspx?PostID=649415</wfw:comment><description>&lt;p&gt;Hello everybody,
&lt;/p&gt;&lt;p&gt;here are some notes comparing "Queued components", "Message Queuing Triggers", "Custom Receivers" options for developing an MSMQ based asynchronous architecture.
&lt;/p&gt;&lt;p&gt;Due to the limitation of "Message Queuing Triggers" in handling concurrent receival of transactional messages, in a recent experience we chose for developing an architecture based on "Custom Receivers".
&lt;/p&gt;&lt;p&gt;hth
&lt;/p&gt;&lt;p&gt;Dario
&lt;/p&gt;&lt;h1&gt;Enterprise Services Queued Components
&lt;/h1&gt;&lt;h2&gt;Advantages:
&lt;/h2&gt;&lt;p style="margin-left: 18pt"&gt;1.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components provide a "built-in" retry mechanism for request failures; this behaviour may be a useful default for exception handling. &lt;br/&gt;Generally this is adequate whenever the target request is idempotent.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;2.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components "built-in" retry mechanism protects also against "Poisoned Messages".
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;3.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components allow the configuration of "Exception classes" to intercept exceptions from outside of the queued component and manage appropriate compensating transactions. 
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;4.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Receive operations can be processed concurrently; concurrency can be administered with the package property "Maximum concurrent players" on the Queuing Tab. 
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;5.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components support distributed transactions by means of COM+.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;6.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components can be used in a clustered environment.&lt;br/&gt;This is generally documented for Microsoft Cluster Server environment only; QC configuration for clustered environment is fairly complicated.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;7.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components support role based authorization.
&lt;/p&gt;&lt;h2&gt;Disadvantages:
&lt;/h2&gt;&lt;p style="margin-left: 18pt"&gt;1.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components need COM+ and use of the "Serviced Component" model.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;2.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components are hosted in the COM+ host process (dllhost).
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;3.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components cannot interact with the queue; the message format is opaque (RPC NDR binary format).
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;4.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Queued Components are designed for use of transactional queues (which is the default).
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;5.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Client and server application are strictly bound to each other. 
&lt;/p&gt;&lt;h2&gt;Additional Considerations:
&lt;/h2&gt;&lt;p&gt;Queued Components provide good scalability and reliability.
&lt;/p&gt;&lt;p&gt;"Serviced Component" model may add complexity to deployment procedures.
&lt;/p&gt;&lt;p&gt;Inability to interact with the message and the queue doesn't allow exploiting some features from the MSMQ transport (eg. Using the response queue).
&lt;/p&gt;&lt;h1&gt;Message Queuing Triggers
&lt;/h1&gt;&lt;h2&gt;Advantages:
&lt;/h2&gt;&lt;p style="margin-left: 18pt"&gt;1.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Message Queuing Triggers support distributed transactions by means of COM+
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;2.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Message Queuing Triggers can be used in a clustered environment.&lt;br/&gt;This is generally documented for Microsoft Cluster Server environment only.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;3.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Message Queuing Triggers allow interaction with the message queue; the message format is defined by the application.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;4.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Message Queuing Triggers can be used with transactional and non transactional queues. 
&lt;/p&gt;&lt;h2&gt;Disadvantages:
&lt;/h2&gt;&lt;p style="margin-left: 18pt"&gt;1.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Message Queuing Triggers don't support automatic administration.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;Some administration features are provided by trigadm utility which is not part of the operating system; trigadm utility can be downloaded from the internet and it has limited supportability.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;2.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Transactional receive() operations are always processed sequentially.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;3.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Message Queuing Triggers cannot be hosted in a process other than mqtgsvc.exe.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;4.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Concurrency for receive operations is difficult to administer and with machine scope only.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;5.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Message Queuing Triggers require use of COM interoperability (do not require use of Serviced Components)
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;6.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Message Queuing Triggers use ActiveX message format. 
&lt;/p&gt;&lt;h2&gt;Additional considerations
&lt;/h2&gt;&lt;p&gt;Serialization of transactional receive() operations may be a too severe limit for scalability.
&lt;/p&gt;&lt;p&gt;Requirement of COM interoperability may add complexity to deployment procedures.  
&lt;/p&gt;&lt;h1&gt;Custom Receivers (developed in .Net)
&lt;/h1&gt;&lt;h2&gt;Advantages:
&lt;/h2&gt;&lt;p style="margin-left: 18pt"&gt;1.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Custom Receivers allow native use of distributed transactions; CR do not require COM interoperability nor use of "enterprise services" model.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;2.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Custom Receivers allow support for clustered environments.&lt;br/&gt;MSMQ cluster support is documented for both Microsoft and Veritas clusters.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;3.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Custom Receivers support concurrent transactional (and non transactional) receive operations.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;4.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Custom Receivers can be administered with xcopy deployment.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;5.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Custom Receivers allow interaction with the queue; the message format is not opaque.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;6.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Custom Receivers allow control of concurrency in receive operations.
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;7.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Custom Receivers can be implemented as stand alone services or as components to be hosted in existing processes. 
&lt;/p&gt;&lt;h2&gt;Disadvantages:
&lt;/h2&gt;&lt;p style="margin-left: 18pt"&gt;1.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Custom Receivers require accurate design for managing transactions, concurrency on receive operations etc..
&lt;/p&gt;&lt;p style="margin-left: 18pt"&gt;2.&lt;span style="font-size:7pt"&gt;      &lt;/span&gt;Custom Receivers require accurate test, especially for handling exceptional conditions, cluster failover etc.&lt;br/&gt;For example, receivers behaviour should be verified carefully with failures on target components, failures msmq operations, handling of poisoned messages etc. 
&lt;/p&gt;&lt;h2&gt;Additional considerations:
&lt;/h2&gt;&lt;p&gt;Custom Receivers can provide ease of administration and good scalability depending on the chosen implementation.
&lt;/p&gt;&lt;p&gt;They generally involve a higher development risk. &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=649415" width="1" height="1"&gt;</description></item></channel></rss>