<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Living .NET&#8230;</title>
	<atom:link href="https://blogs.msmvps.com/manoj/feed/" rel="self" type="application/rss+xml" />
	<link>https://blogs.msmvps.com/manoj</link>
	<description>Just another Microsoft MVPs site</description>
	<lastBuildDate>Thu, 06 Aug 2009 10:39:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.6.2</generator>
	<item>
		<title>Why I don&#8217;t like ASP.NET anymore</title>
		<link>https://blogs.msmvps.com/manoj/2009/08/06/why-i-don-t-like-asp-net-anymore/</link>
					<comments>https://blogs.msmvps.com/manoj/2009/08/06/why-i-don-t-like-asp-net-anymore/#comments</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Thu, 06 Aug 2009 10:39:00 +0000</pubDate>
				<category><![CDATA[11183]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2009/08/06/why-i-don-t-like-asp-net-anymore.aspx</guid>

					<description><![CDATA[When I first started using ASP.NET (back in the .NET 1.0 days), I was in awe of the sheer capabilities it offered. For a humble ASP/VB developer, this was a welcome change. The Page object model seemed to be a work of art. &#8220;Code-behind&#8221; seemed to be one of the coolest things.&#160;&#160; Eight years down the line, my perspective has slowly started to change. All of a sudden, I have started to question the very design of ASP.NET (at least the object model and the Page Lifecycle). I have started to feel that the design is simply over-complicated. Let me &#8230; <a href="https://blogs.msmvps.com/manoj/2009/08/06/why-i-don-t-like-asp-net-anymore/" class="more-link">Continue reading Why I don&#8217;t like ASP.NET anymore</a>]]></description>
										<content:encoded><![CDATA[<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">When I first started using ASP.NET (back in the .NET 1.0 days), I was in awe of the sheer capabilities it offered. For a humble ASP/VB developer, this was a welcome change. The Page object model seemed to be a work of art. &ldquo;Code-behind&rdquo; seemed to be one of the coolest things.&nbsp;</span><span style="font-size: 10pt;font-family: Arial">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">Eight years down the line, my perspective has slowly started to change. All of a sudden, I have started to question the very design of ASP.NET (at least the object model and the Page Lifecycle). I have started to feel that the design is simply over-complicated. Let me give you examples of where I feel this pinch:</span><span style="font-size: 10pt;font-family: Arial">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"></span><span style="font-size: 10pt;font-family: Arial"><span>1)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt;font-family: Arial"><strong>Code-Behind is always a mess</strong></span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"></span><span style="font-size: 10pt;font-family: Arial">For ASP developers, developing screens using C# (or VB.NET) was a boon. Spaghetti code wasn&rsquo;t there any more. All the power came in the form of code-behind. I liked code-behind to start with. But as and when we started to develop complex web applications (with rich UI), the code in code-behind files simply got worse by the day. </span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"></span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">Web Client Software factory and the MVP pattern came in to reduce this mess to some extent. But I suppose, they arrived a bit too late. By that time, you already had applications with thousands of lines of code in each code behind file. WCSF and MVP only do so much. To date, I have never seen code behind classes which are not a mess. No matter how hard you try, you cannot keep code tidy. I know it is just not me, as I see hundreds of applications in the community which have the same plight.</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"></span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">Have a look at this piece of code, which I simply couldn&rsquo;t do anything about. I have an editable grid with two editable columns &ndash; one a dropdown and the other is a text field (date). In this event, I am basically:</span></p>
<ol>
<li>
<div class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"><span><span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt;font-family: Arial">Binding a list to the drop down</span></div>
</li>
<li>
<div class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"></span><span style="font-size: 10pt;font-family: Arial"><span><span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt;font-family: Arial">Adding a delete command to each row, which is enabled conditionall</span></div>
</li>
<li>
<div class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"></span><span style="font-size: 10pt;font-family: Arial"><span><span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt;font-family: Arial">Disabling the fields if the record is not a new one.</span></div>
</li>
</ol>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"></span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">protected void gvReports_RowDataBound(object sender, GridViewRowEventArgs e)<br />{<br />&nbsp;if (e.Row.RowType == DataControlRowType.DataRow)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DropDownList reportTypeList = (DropDownList)e.Row.Cells[0].Controls[1];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reportTypeList.DataSource = _reportTypes;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reportTypeList.DataBind();</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Models.Report report = (Models.Report)e.Row.DataItem;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Button deleteCommand = (Button)e.Row.Cells[2].Controls[0];</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (report.CanDelete)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deleteCommand.OnClientClick = string.Format(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;if(!confirm(&#8216;Are you sure you want to untag this report?&#8217;))return;&#8221;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deleteCommand.Enabled = false;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TextBox reportDate = (TextBox)e.Row.Cells[1].Controls[1];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reportDate.Text = report.ReportDate.ToShortDateString();</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (report.ReportID &gt; 0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reportDate.Enabled = false;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reportTypeList.Enabled = false;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;}<br /></span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">I don&rsquo;t know about you, but I simply don&rsquo;t like the above code block. Without hefty comments, you wouldn&rsquo;t have a clue what is happening in this block. Help me make this better. Don&rsquo;t even bother to ask how I did the validations for the fields in this grid.</span><span style="font-size: 10pt;font-family: Arial">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">2) </span><span style="font-size: 10pt;font-family: Arial"><strong>Spaghetti Code will not go away</strong></span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">One of the banes of ASP was spaghetti code &ndash; server script and client script being mixed together. ASP.NET removes most of the pain, but not all of it. I find myself bringing in server script in many places. Here is an example:</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ASP.NET randomly generates control ids at runtime when controls are placed in containers or they are in pages having a master. To access these controls on the client script (to do validations, changing style etc), you could end up doing something like this:</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">var divReports = document.getElementById(&#8216;&lt;%= reportsSection.ClientID %&gt;&#8217;);<br />divReports.style.display = &#8216;none&#8217;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial"><br /></span><span style="font-size: 10pt;font-family: Arial"><span>3)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;<strong>&nbsp;&nbsp;&nbsp; </strong></span></span></span><span style="font-size: 10pt;font-family: Arial"><strong>No Client Side Object Model</strong></span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">No matter how powerful the server side object model</span><span style="font-size: 10pt;font-family: 'Courier New'">, </span><span style="font-size: 10pt;font-family: Arial">tons of code still needs to be written in JavaScript. The bigger problem is that ASP.NET controls don&rsquo;t really have a client side object model which mirrors the server side object model. Therefore, you end up either writing a lot of spaghetti code as shown above or hacking the DOM which the server side controls creates. I see that many 3<sup>rd</sup> party controls (like Telerik, Infragistics etc) actually offer a client side object model. I am not sure why it was not offered by the ASP.NET server controls to start with.</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">&nbsp;</span><span style="font-size: 10pt;font-family: Arial"><span>4)<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt;font-family: Arial"><strong>Painfully complex page lifecycle</strong></span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">For people who have developed &ldquo;Portal&rdquo; like applications, they would more than agree with me that the code would be horrendously complex, especially the container page which hosts the user controls. There are so many subtleties in the order of the events between the page and the user controls; you would get lost debugging through it. ViewState and master page add to the spice. Sometimes you begin to think that the idea of System.Web.UI.Control was a bad one.</span><span style="font-size: 10pt;font-family: Arial">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt;font-family: Arial">I have provided a few examples why I have started to dislike ASP.NET. I strongly believe MVC is the right way to develop ASP.NET applications. But unfortunately, it has arrived way too late for ASP.NET developers and the damage has already been done. Moreover, application stakeholders would have concerns to develop stuff on MVC as there is not much 3<sup>rd</sup> party control support as of now. In other words, developing rich UI with MVC would just be too big a challenge to deal with. Be that as it may, code behind will stay for some more time to come, and that is unfortunate. </span></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2009/08/06/why-i-don-t-like-asp-net-anymore/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Using Interception with Dependency Injection: EL 4.1 and Unity Spring 1.2 create new avenues</title>
		<link>https://blogs.msmvps.com/manoj/2009/01/16/using-interception-with-dependency-injection-el-4-1-and-unity-spring-1-2-create-new-avenues/</link>
					<comments>https://blogs.msmvps.com/manoj/2009/01/16/using-interception-with-dependency-injection-el-4-1-and-unity-spring-1-2-create-new-avenues/#respond</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Fri, 16 Jan 2009 03:50:00 +0000</pubDate>
				<category><![CDATA[9690]]></category>
		<category><![CDATA[9691]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2009/01/16/using-interception-with-dependency-injection-el-4-1-and-unity-spring-1-2-create-new-avenues.aspx</guid>

					<description><![CDATA[It is customary to conceive any large application to be composed of several logical layers. It is also a practice to reduce the coupling between the layers. Typically, one would create an interface&#160; for each class of each layer and they would be coupled to the downstream layer classes only though interfaces. &#160;&#160; You would also typically want to unit test each class in each layer. By definition, each of unit test would test a method of only one class and not the downstream classes it depends on. To achieve this , one would need to mock out the instances &#8230; <a href="https://blogs.msmvps.com/manoj/2009/01/16/using-interception-with-dependency-injection-el-4-1-and-unity-spring-1-2-create-new-avenues/" class="more-link">Continue reading Using Interception with Dependency Injection: EL 4.1 and Unity Spring 1.2 create new avenues</a>]]></description>
										<content:encoded><![CDATA[<p>It is customary to conceive any large application to be composed of several logical layers. It is also a practice to reduce the coupling between the layers. Typically, one would create an interface&nbsp; for each class of each layer and they would be coupled to the downstream layer classes only though interfaces.</p>
<p>&nbsp;&nbsp; <br />You would also typically want to unit test each class in each layer. By definition, each of unit test would test a method of only one class and not the downstream classes it depends on. To achieve this , one would need to mock out the instances of the classes which the class being unit-tested depends on.&nbsp; To bring all of this to play effectively, you need&nbsp; to implement the Dependency Injection pattern in your application. Dependency injection is provided by Unity application block.</p>
<p>The application we talked about earlier has in addition to a lot of business logic, several pieces of cross cutting logic &#8211; logic applicable to all classes &#8211; like logging, tracing, authorization, validation etc. The code for these concerns are usually generic. It would be an awful amount of work to implement these generic pieces of code in every class&nbsp; (or a group of classes) of your application. What you really need is some way to stitch these concerns into the application without disturbing the application code too much. This style of programming is called Aspect Oriented programming (sort of).&nbsp; This capability is provided by the Policy Injection Application block. </p>
<p>Now, to me, both aspects&nbsp; discussed above are very important to any application. In other words, any application would need both dependency injection along with some type of aspect orientation (or policy injection or interception).&nbsp; The question really is &#8211; how do you really bring them together?</p>
<p>I am assuming that you are familiar with these blocks I just mentioned. To have rubber meet the road, we really need to marry IContainer.Resolve&lt;T&gt; and&nbsp; PolicyInjection.Create&lt;T&gt;(). This was not possible&nbsp; as of EL 4.0 and left me hoping. It is possible now &#8211; with EL 4.1 (along Unity 1.2). The interception capability comes as a extension which can be associated with the Unity container. Therefore, you can have policies associated with the container which govern which call handlers are added. The real beauty is this &#8211; the application classes really work with the IContainer interface. In an actual environment, you need to associate the container which has the correct dependencies and interception policies. The unit testing environment would basically replace the container with one where the Interception extension is not applied, and therefore, the unit tests would not really execute any cross-cutting logic (of course, you can choose otherwise). Neat!</p>
<p>I have just started to dabble with this ability, and a lot of questions still need to be answered. One that comes immediately from the top of my mind is performance. When a class is set to be intercepted, what would be the performance overhead, and what would be the overhead based on the type of interceptor (TransparentProxyInterceptor, VirtualMethodInterceptor or InterfaceInterceptor)? Obviously, there are no definitive answers and it all depends on the policies and handlers you add to your application. I have a reason to believe that the cost of interception is not usually so high, that is deemed only for academic purposes. One would need to perform relevant tests to ratify the same in her application on the representative environment. The second question, but seemingly more subtle, is instancing. The new interception features either work on the RealProxy based interception, or dynamic code generation.&nbsp; Obviously, it would be more efficient to reuse these instances at runtime instead of generating them for every call. Now, if you have singleton instancing, the real question is about thread safety. How does a dynamically generated instance serve multiple request threads at a time &#8211; as it happens in web applications in production? </p>
<p>Having opened these questions, I would write up a follow-up post which hopefully addresses these. In the meantime, I will dabble with more scenarios using these new capabilities, and keep you posted.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2009/01/16/using-interception-with-dependency-injection-el-4-1-and-unity-spring-1-2-create-new-avenues/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Best practices in Workflow Design &#8211; Part 2</title>
		<link>https://blogs.msmvps.com/manoj/2008/07/14/best-practices-in-workflow-design-part-2/</link>
					<comments>https://blogs.msmvps.com/manoj/2008/07/14/best-practices-in-workflow-design-part-2/#respond</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Mon, 14 Jul 2008 17:36:00 +0000</pubDate>
				<category><![CDATA[8138]]></category>
		<category><![CDATA[8179]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2008/07/15/best-practices-in-workflow-design-part-2.aspx</guid>

					<description><![CDATA[Naming convention in Workflows Workflow activities should be named appropriately. As much as possible, they should reflect names form the business domain. For example, it wouldn&#8217;t appear good to have names like ifelseActivity1 or callExternalMethodActivity1. Instead, it is good to have names like ifProductsExists and MakePayment respectively. Shown below is a good example of the same: Custom activity names should really represent their purpose. Good examples are ApproveRequestActivity. It is customary to suffix custom activity classes with &#8220;Activity&#8221;. It is also a good practice to provide apt descriptions to all the activities in the workflow. This would help better understand &#8230; <a href="https://blogs.msmvps.com/manoj/2008/07/14/best-practices-in-workflow-design-part-2/" class="more-link">Continue reading Best practices in Workflow Design &#8211; Part 2</a>]]></description>
										<content:encoded><![CDATA[<p><strong>Naming convention in Workflows</strong></p>
<p>Workflow activities should be named appropriately. As much as possible, they should reflect names form the business domain. For example, it wouldn&rsquo;t appear good to have names like ifelseActivity1 or callExternalMethodActivity1. Instead, it is good to have names like ifProductsExists and MakePayment respectively. Shown below is a good example of the same:</p>
<p><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/manoj.Images/WFNamingConventions.JPG" alt="Good Naming conventions" /></p>
<p>Custom activity names should really represent their purpose. Good examples are ApproveRequestActivity. It is customary to suffix custom activity classes with &ldquo;Activity&rdquo;. It is also a good practice to provide apt descriptions to all the activities in the workflow. This would help better understand the nuances of the workflow logic.</p>
<p><strong>Transactions in Workflows</strong></p>
<p>In application design, avoid scenarios in which transactions need to span between business components and workflow logic. Either a database transaction should complete before the workflow is invoked, or should be started and completed within the execution of the workflow sequence (using a TransactionScope activity, for example). In either case, care must be taken to ensure that the transaction (and hence, locks on shared resources) should not be kept alive for a long period, as this adversely impacts performance. For long running transactions, compensation should be employed for undoing the effects of a prior transaction. WF has adequate measures (compensatable activities) to incorporate the same.</p>
<p><strong>Sequential versus State machine workflow</strong></p>
<p>It is definitely possible to represent a workflow scenario of a business application as a sequential or a state machine workflow. State machine workflows appear to be the right logical choice for long running business operations, which can typically be visualized as those transitioning from one state to another by means of some human or process input. A sequential workflow may be harder to represent the entire workflow process in these cases, thought it is not impossible.&nbsp;</p>
<p>State machine workflows also provide for better tracking of the process. Since each state in a state-machine workflow represents a logical step in a business process, the give better visibility into the current state of the process. Refer to <a target="_blank" href="http://blogs.msdn.com/pravin_indurkar/archive/2005/09/25/473826.aspx">this blog post</a> for more info on the usefulness of state machine workflows.<br />Note that states within a state machine could have sequence of activities. Sequential workflows have their own place and have to be used appropriately.</p>
<p><strong>Workflow Instance Identifiers &#8211; Correlation</strong></p>
<p>Workflow scenarios, typically state machine ones, involve persistence. Here, the workflow waits for an event to occur and hence its state is persisted into the database. The workflow is brought to life by another part of the application which loads the hydrated instance and executes the workflow (perhaps transitions it to the next state). The unloading and loading is correlated by the WorflowInstanceId (a Guid value). It is the application&rsquo;s responsibility to keep this value and then use it at a later point of time. It could be a wise thing to store this value in the database alongside with the other information and then fetch the same for correlation at a later point of time.</p>
<p>It is perhaps, not a good practice to wait for the runtime to start the workflow so as to get the WorkflowInstanceId.&nbsp;A better approach is to generate the Guid value and pass it the workflow runtime as a parameter.&nbsp;This helps in situations where starting a workflow is a small part of a transactional business operation, and you need to keep the WF runtime pieces out of transaction scope.</p>
<p><strong>Error Handling in Workflows</strong></p>
<p>It is important to understand that error handling in workflows is as important as those in the business components.&nbsp; Workflows that encounter an error, either through an exception thrown by a called service or that is raised internally, go in faulted state and complete prematurely. Since the execution nature of workflow is asynchronous, unhandled exceptions are not raised to the application and go unnoticed. This could adversely affect several parts of the application expecting a persisted workflow, especially in the case of a state machine workflow. Since the faulted workflow goes to the closed state, the application expecting the workflow to be in a specific state is left in an unrecoverable situation.</p>
<p>To avoid such situations, one should include appropriate fault handlers in the workflow.&nbsp; An example of the same is shown in the figure below. It would be the responsibility of the fault handler to take the workflow to a recoverable state. The fault handler could do things like logging the exception details, persist recovery information and so on, analogous to a catch block in C#.</p>
<p><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/manoj.Images/WFErrHandling.JPG" alt="Error handling in State Machine Workflows" /></p>
<p>State machine workflows are to be handled in a different way. State machine workflows do not have a workflow-wide fault handler collection (it does not make sense either). Here, one should provide a fault handler for every sub-activity within each state activity. It is a good practice to keep the semantics of a state machine even in the event of a fault. This can be done by having the fault handler move the workflow to a user-defined error state. At this state, the workflow could either wait for recovery to happen, might just log and exception and move to completed state, or whatever is the apt handling logic for the application. You could consider options for retrying for a fixed number of times as well.<br /><strong>&nbsp;<br />Workflow Cancellation</strong></p>
<p>Cancellation of workflows is handled similar to Faults. One should wire appropriate Cancellation handlers to every activity. Like a fault handler, the cancel handler should gracefully close a workflow by taking the appropriate action.<br /><strong>&nbsp;</strong></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2008/07/14/best-practices-in-workflow-design-part-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Best practices in Workflow Design &#8211; Part 1</title>
		<link>https://blogs.msmvps.com/manoj/2008/07/11/best-practices-in-workflow-design-part-1/</link>
					<comments>https://blogs.msmvps.com/manoj/2008/07/11/best-practices-in-workflow-design-part-1/#comments</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Fri, 11 Jul 2008 19:00:00 +0000</pubDate>
				<category><![CDATA[8138]]></category>
		<category><![CDATA[8179]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2008/07/12/Best-practices-in-Workflow-Design-_2D00_-Part-1.aspx</guid>

					<description><![CDATA[It&#8217;s been a awfully long time since I have published a blog entry, and it seems like the world of technology has changed quite a bit since! The hiatus is over now, and I would like to starting putting down some thoughts and experiences on my new interest &#8211; Connected Systems. WF and WCF are the pretty much the atoms for building connected systems on the .NET platform, and a large percentage of my upcoming posts would be focused on these technologies. In this post, I want to talk about some aspects of workflow design based on my experience, which &#8230; <a href="https://blogs.msmvps.com/manoj/2008/07/11/best-practices-in-workflow-design-part-1/" class="more-link">Continue reading Best practices in Workflow Design &#8211; Part 1</a>]]></description>
										<content:encoded><![CDATA[<p>It&rsquo;s been a awfully long time since I have published a blog entry, and it seems like the world of technology has changed quite a bit since! The hiatus is over now, and I would like to starting putting down some thoughts and experiences on my new interest &ndash; Connected Systems. WF and WCF are the pretty much the atoms for building connected systems on the .NET platform, and a large percentage of my upcoming posts would be focused on these technologies. </p>
<p>In this post, I want to talk about some aspects of workflow design based on my experience, which I think can be classified as idioms or best practices.</p>
<p><strong><span style="text-decoration: underline"></p>
<p>Workflows should contain only &lsquo;flow of logic&rsquo; and not the logic itself</p>
<p></span></strong></p>
<p>It is easy to visualize workflows as business logic which is&nbsp;modeled&nbsp;using a designer. It is common to see developers transform their typical business logic into workflows by separating different parts of the logic into separate workflow activities. Here, we see lots of procedural code gets transformed into workflow models.&nbsp;This is clearly not the right thing to do. Workflows are not be be plain replacement for existing business logic components. Workflows are to be used in specific scenarios &#8211; like long running business processes, rule driven logic, dynamic flow changes etc (I&#8217;ll cover this&nbsp;in a later post as well). </p>
<p>The figure shown below contains a snippet of a bad workflow design where procedural logic is transformed to a workflow through usage of code activities (in an order processing application):</p>
<p><img loading="lazy" width="555" src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/manoj/BadWFDesign.JPG" alt="Bad Workflow Design" height="626" /></p>
<p><strong><span style="text-decoration: underline">Avoid business logic code within workflows</span></strong></p>
<p>Ideally, workflows should not contain busines code themselves. In other words, as much as possible, usage of CodeActivity should be avoided (at least, it should not contain business logic). One way to take out business logic contained in code activities is to replace them with CallExternalMethod activity, where you invoke upon a method of a registered service. A better way would be to create a custom activity, where we override the Execute method, and within it delegate the business operation to a registered service. This way, taking individual pieces of business logic out of the workflow&nbsp;also helps us to unit test them in&nbsp;isolation. If a workflow is designed well, it would not have any code in its code-behind logic. This approach would also help us in scenarios where we have only XAML-based activation of workflows.</p>
<p>Given below is a snippet of a custom activity which is used in the Purchase Order creation workflow, and updates the status of a workflow in the database. The Execute method contains the usage of a registered service to which the business operation is delegated to (updating of the status field in this case). </p>
<div>
<p class="MsoNormal"><span style="font-size: 9pt;color: #0000ff;font-family: 'Courier New'">public</span><span style="font-size: 9pt;font-family: 'Courier New'"> <span style="color: #0000ff">partial</span> <span style="color: #0000ff">class</span> <span style="color: #2b91af">UpdateOrderStatusActivity</span>: <span style="color: #2b91af">Activity</span></span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'">{</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #2b91af">DependencyProperty</span> PurchaseOrderProperty = <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">&#8220;PurchaseOrder&#8221;</span>, <span style="color: #0000ff">typeof</span>(<span style="color: #2b91af">PurchaseOrder</span>), <span style="color: #0000ff">typeof</span>(<span style="color: #2b91af">UpdateOrderStatusActivity</span>));</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">public</span> <span style="color: #2b91af">PurchaseOrder</span> PurchaseOrder</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">get</span> { <span style="color: #0000ff">return</span> (<span style="color: #2b91af">PurchaseOrder</span>)<span style="color: #0000ff">base</span>.GetValue(PurchaseOrderProperty); }</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">set</span> { <span style="color: #0000ff">base</span>.SetValue(PurchaseOrderProperty, <span style="color: #0000ff">value</span>); }</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p class="MsoNormal"><span style="font-size: 9pt;color: #0000ff;font-family: 'Courier New'">private</span><span style="font-size: 9pt;font-family: 'Courier New'"> <span style="color: #0000ff">static</span> <span style="color: #2b91af">DependencyProperty</span> OrderStatusProperty = <span style="color: #2b91af">DependencyProperty</span>.Register(<span style="color: #a31515">&#8220;OrderStatus&#8221;</span>, <span style="color: #0000ff">typeof</span>(<span style="color: #0000ff">string</span>), <span style="color: #0000ff">typeof</span>(<span style="color: #2b91af">UpdateOrderStatusActivity</span>));</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> OrderStatus</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">get</span> { <span style="color: #0000ff">return</span> (<span style="color: #0000ff">string</span>)<span style="color: #0000ff">base</span>.GetValue(OrderStatusProperty); }</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">set</span> { <span style="color: #0000ff">base</span>.SetValue(OrderStatusProperty, <span style="color: #0000ff">value</span>); }</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">public</span> UpdateOrderStatusActivity()</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>InitializeComponent();</span></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal"><b><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></b></p>
<p class="MsoNormal"><b><span style="font-size: 9pt;font-family: 'Courier New'">&nbsp;</span></b></p>
<p class="MsoNormal"><b><span style="font-size: 9pt;color: #0000ff;font-family: 'Courier New'">protected</span></b><b><span style="font-size: 9pt;font-family: 'Courier New'"> <span style="color: #0000ff">override</span> <span style="color: #2b91af">ActivityExecutionStatus</span> Execute(<span style="color: #2b91af">ActivityExecutionContext</span> executionContext)</span></b></p>
<p class="MsoNormal"><b><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></b></p>
<p class="MsoNormal"><b><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #2b91af">IOrderProcessWFService</span> orderService = executionContext.GetService&lt;<span style="color: #2b91af">IOrderProcessWFService</span>&gt;();</span></b></p>
<p class="MsoNormal"><b><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>orderService.UpdateOrderStatus(PurchaseOrder,OrderStatus);</span></b></p>
<p class="MsoNormal"><b><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">return</span> <span style="color: #2b91af">ActivityExecutionStatus</span>.Closed;</span></b></p>
<p class="MsoNormal"><b><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></b></p>
<p class="MsoNormal"><span style="font-size: 9pt;font-family: 'Courier New'"><span>&nbsp;&nbsp; </span>}</span></p>
</div>
<p class="MsoNormal"><i><span style="font-size: small;font-family: Calibri">&nbsp;</span></i></p>
<p class="MsoNormal">I&#8217;ll try to cover more best practices in my next post. If you have better suggestions or comments, please do share it!</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2008/07/11/best-practices-in-workflow-design-part-1/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>WCF &#8211; A Perspective</title>
		<link>https://blogs.msmvps.com/manoj/2007/01/14/wcf-a-perspective/</link>
					<comments>https://blogs.msmvps.com/manoj/2007/01/14/wcf-a-perspective/#respond</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Sun, 14 Jan 2007 05:24:00 +0000</pubDate>
				<category><![CDATA[3130]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2007/01/14/wcf-a-perspective.aspx</guid>

					<description><![CDATA[.NET 3.0 has been made available to all the developers recently. With it comes a set of new set of API, which are simply there to unleash the .NET developer’s potential to create the next wave of powerful applications. These API, formerly called WinFX, take the form of four pillars – WCF, WF, WPF and WCS. In this post of mine, I would like to give a perspective on the Windows Communication Foundation (WCF).&#160; Most typically, one starts off an introduction to WCF by explaining the four tenets of SOA, and how WCF embraces them from the ground-up. While this &#8230; <a href="https://blogs.msmvps.com/manoj/2007/01/14/wcf-a-perspective/" class="more-link">Continue reading WCF &#8211; A Perspective</a>]]></description>
										<content:encoded><![CDATA[<p><P><FONT face="verdana,geneva" color="#000066">.NET 3.0 has been made available to all the developers recently. With it comes a set of new set of API, which are simply there to unleash the .NET developer’s potential to create the next wave of powerful applications. These API, formerly called WinFX, take the form of four pillars – </FONT><A class="" title="WCF" href="http://wcf.netfx3.com/" target="_blank"><FONT face="verdana,geneva" color="#0066ff"><STRONG>WCF</STRONG></FONT></A><FONT face="verdana,geneva" color="#000066">, </FONT><A class="" title="WF" href="http://wf.netfx3.com/" target="_blank"><FONT face="verdana,geneva" color="#0066ff"><STRONG>WF</STRONG></FONT></A><FONT face="verdana,geneva" color="#000066">, </FONT><A class="" title="WPF" href="http://wpf.netfx3.com/" target="_blank"><FONT face="verdana,geneva" color="#0066ff"><STRONG>WPF</STRONG></FONT></A><FONT face="verdana,geneva"><FONT color="#000066"><STRONG> </STRONG>and </FONT></FONT><A class="" title="WCS" href="http://cardspace.netfx3.com/" target="_blank"><FONT face="verdana,geneva" color="#0066ff"><STRONG>WCS</STRONG></FONT></A><FONT face="verdana,geneva" color="#000066">. In this post of mine, I would like to give a perspective on the Windows Communication Foundation (WCF).&nbsp; </FONT></P><br />
<P><FONT face="verdana,geneva" color="#000066">Most typically, one starts off an introduction to WCF by explaining the four tenets of SOA, and how WCF embraces them from the ground-up. While this is very reasonable, I would like to think about WCF from a slightly different perspective which, of course, would eventually flow into confluence of the SOA tenets. To get a great insight into these tenets, I would urge you to look into </FONT><A class="" title="SOA Tenets" href="http://msdn.microsoft.com/msdnmag/issues/04/01/Indigo/" target="_blank"><FONT face="verdana,geneva" color="#0066ff"><STRONG>this paper</STRONG></FONT></A><FONT face="verdana,geneva" color="#000066"> by the venerable Don Box.</FONT></P><br />
<P><FONT face="verdana,geneva" color="#000066">WCF, in a nutshell, is all about facilitating <U><STRONG>message</STRONG></U> exchanges between <U><STRONG>endpoints</STRONG></U>. Note that ‘message’ and ‘endpoint’ are underlined. Well, these are but, what WCF is all about. These are concepts through which SOA is realized. Let me give you my understanding on these concepts:</FONT></P><br />
<P><FONT face="verdana,geneva" color="#000066">If any entity needs to communicate with the world, it does so with Endpoints. Endpoint comprises of three elements (commonly called as ABC):</FONT><FONT face="verdana,geneva"><BR><FONT color="#000066">Address (Where)&nbsp; &#8211; Where can I find the service, the URI?<BR>Binding (How) &#8211; How can I communicate with the service? What are security requirements, encoding requirements etc.? <BR>Contract (What) – What is the structure of the messages that I need to communicate with the endpoint?&nbsp; What are the message exchange patterns (like Request/Reply, OneWay etc)</FONT></FONT></P><br />
<P><FONT face="verdana,geneva" color="#000066">A WCF service would therefore, have at least one endpoint; it could have multiple based on different combinations of bindings, contracts or endpoint addresses. </FONT></P><br />
<P><FONT face="verdana,geneva" color="#000066">If you really look at it, the concepts embodied by WCF aren’t new. They were pretty much present in ASMX. What lacked was that these concepts/abstractions were not explicitly codified in the ASMX (ASP.NET) framework.&nbsp; ASMX just seemed to be a quick way to get .NET classes to talk SOAP. So, caught in a world of classes and attributes, developers lost sight of underlying concepts that manifested as <EM>wsdl:portType, wsdl:port, wsdl:message</EM> and <EM>wsdl:binding</EM>. </FONT></P><br />
<P><FONT face="verdana,geneva" color="#000066">WCF, on the other hand makes these concepts explicit, as seen in the <EM>ServiceEndPoint</EM>, <EM>Binding</EM>,&nbsp; <EM>ContractDescription</EM>, and <EM>EndPointAddress</EM> classes in the <EM>System.ServiceModel</EM> namespace. It is this object model that makes WCF very powerful. The number of out-of-the-box bindings available, and the existence of several extensibility points speak of the raw power of the WCF programming model. Also, this architecture is what makes unification of several programming models like MSMQ, COM+, WSE etc. possible.</FONT></P><br />
<P><FONT face="verdana,geneva" color="#000066">“Message”, which can simply be thought of as the data/document/information exchanged between endpoints, is a first class citizen in the WCF programming model. Unlike its predecessor, where messages meant no more than an XML document (or stream) representing the SOAP envelope, WCF provides much better representation and finer control over messages. Messages are represented by the <EM>Message</EM> abstract class in the <EM>System.ServiceModel.Channels </EM>namespace.</FONT></P><br />
<P><FONT face="verdana,geneva" color="#000066">Having seen how endpoints and messages are dealt with in WCF, it can be safely asserted that we are now consciously moving from the procedure call paradigm to a message exchange paradigm.</FONT></P><br />
<P><FONT face="verdana,geneva"><FONT color="#000066">To find out more about WCF architecture, and the core classes that make up WCF, refer to </FONT><A class="" title="WCF Arch" href="http://www.yassers.com/content/soa/WCFArchOverview.aspx" target="_blank"><STRONG><FONT color="#0066ff">this excellent paper</FONT></STRONG></A><FONT color="#000066"> by Yasser Shohoud.</FONT></FONT></P><br />
<P><FONT face="Verdana" color="#000066" size="3"><STRONG>Update:</STRONG></FONT></P><br />
<P><FONT face="Verdana" color="#000066">As a part of the community launch of&nbsp;Windows Vista and Office 2007&nbsp;in the <A class="" href="http://groups.msn.com/bdotnet" target="_blank"><STRONG><FONT color="#0000ff">B.NET User Group</FONT></STRONG></A>, we, a group of MVPs and other active community members authored a small e-book, comprising of articles on Vista, .NET 3.0 and Office 2007. Based on this post of mine, I wrote an article on what I thought the underpinnings concepts of WCF were. You could download the PDF of the e-book <STRONG><FONT color="#0033ff"><A class="" title="e-book" href="http://www.4shared.com/file/11433779/c6712691/BDOTNET_UG_Book_feb_2007.html" target="_blank">here</A></FONT></STRONG>.</FONT></P><br />
<P><FONT face="Verdana" color="#000066"></FONT><FONT face="verdana,geneva">&nbsp;</P><br />
<P><BR></P></FONT></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2007/01/14/wcf-a-perspective/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Implementing Timeout &#038; Retry</title>
		<link>https://blogs.msmvps.com/manoj/2006/11/01/implementing-timeout-retry/</link>
					<comments>https://blogs.msmvps.com/manoj/2006/11/01/implementing-timeout-retry/#respond</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Wed, 01 Nov 2006 06:58:00 +0000</pubDate>
				<category><![CDATA[2343]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2006/11/01/Implementing-Timeout-_2600_-Retry.aspx</guid>

					<description><![CDATA[I have come across several situations where I need some sort of Timeout functionality for a particular operation. At the same time, I also needed a provision for retrying the operation a few times before calling quits. I thought about a solution using ManualResetEvent and a Timer which I have outlined below: const&#160;int&#160;MAX_RETRIES&#160;=&#160;5;const&#160;int&#160;RETRY_INTERVAL&#160;=&#160;10;&#160;&#160;&#160;&#160;//10&#160;secondsconst&#160;int&#160;OPERATION_TIMEOUT&#160;=&#160;1;&#160;//1&#160;minute static&#160;void&#160;DoOperation(){&#160;&#160;&#160;&#160;int&#160;retries&#160;=&#160;0;&#160;&#160;&#160;&#160;int&#160;timeout&#160;=&#160;0; &#160;&#160;&#160;&#160;ManualResetEvent&#160;waitHandle&#160;=&#160;new&#160;ManualResetEvent(false); &#160;&#160;&#160;&#160;//Use&#160;a&#160;timer&#160;to&#160;retry&#160;the&#160;opeation&#160;periodically&#160;&#160;&#160;&#160;Timer&#160;retryTimer&#160;=&#160;null;&#160;&#160;&#160;&#160;retryTimer&#160;=&#160;new&#160;Timer(&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;new&#160;TimerCallback(&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//The&#160;operation&#160;to&#160;carry&#160;out&#160;is&#160;represented&#160;by&#160;this&#160;anonymous&#160;method.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delegate(object&#160;state)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;try&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if&#160;(retries&#160;&#62;&#160;0)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//The&#160;operation&#160;has&#160;failed&#160;before.&#160;So&#160;you&#160;may&#160;want&#160;to&#160;handle&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&#160;that&#160;situation&#160;here.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Console.WriteLine(&#34;Retry&#160;attempt:&#160;{0}&#34;,&#160;retries);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;} &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//Do&#160;the&#160;operation&#160;which&#160;may&#160;fail&#160;or&#160;timeout.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Console.WriteLine(&#34;Doing&#160;some&#160;major&#160;operation&#160;now.&#34;); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//throw&#160;new&#160;Exception(&#34;Some&#160;exception&#34;);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//Thread.Sleep(1000); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//Checking&#160;whether&#160;the&#160;operation&#160;timed&#160;out.&#160;In&#160;this&#160;case,&#160;the&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&#160;thread&#160;isnt&#160;forcefully&#160;aborted,&#160;so&#160;you&#160;can&#160;exit&#160;gracefully&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//Else,&#160;you&#160;may&#160;need&#160;to&#160;handle&#160;the&#160;ThreadAbortException&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if&#160;(timeout&#160;==&#160;ManualResetEvent.WaitTimeout)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Console.WriteLine(&#34;It&#160;seems&#160;that&#160;the&#160;operation&#160;timed&#160;out.&#160;Need&#160;to&#160;exit&#160;gracefully&#34;);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;else&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Console.WriteLine(&#34;Operation&#160;completed&#34;);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;} &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//Set&#160;the&#160;waithandle&#160;if&#160;the&#160;opeation&#160;is&#160;successful&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;waitHandle.Set(); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//Everything&#160;went&#160;well.&#160;Close&#160;the&#160;timer.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;retryTimer.Dispose();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;catch&#160;(Exception&#160;e)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&#160;Handle&#160;the&#160;exception &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;retries++; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//Check&#160;if&#160;the&#160;number&#160;of&#160;retries&#160;has&#160;exceeded&#160;the&#160;maximum&#160;allowed&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if&#160;(retries&#160;&#62;&#160;MAX_RETRIES)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//Do&#160;some&#160;logic&#160;to&#160;handle&#160;this&#160;situation&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Console.WriteLine(&#34;Operation&#160;has&#160;exceeded&#160;maximum&#160;attempts&#34;); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&#160;Set&#160;the&#160;waitHandle&#160;so&#160;that&#160;the&#160;method&#160;returns&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;waitHandle.Set();&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;else&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//Retry&#160;the&#160;operation&#160;or&#160;any&#160;do&#160;alternative&#160;logic&#160;here&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Console.WriteLine(&#34;The&#160;operation&#160;failed&#160;and&#160;will&#160;be&#160;retried&#160;in&#160;a&#160;short&#160;while.&#34;);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}),&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;null,&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;new&#160;TimeSpan(0,&#160;0,&#160;0),&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;new&#160;TimeSpan(0,&#160;0,&#160;RETRY_INTERVAL));&#160;//&#160;The&#160;timer&#160;retries&#160;the&#160;operation&#160;for&#160;the&#160;specified&#160;interval &#160;&#160;&#160;&#160;//Wait&#160;for&#160;the&#160;operation&#160;to&#160;complete&#160;or&#160;timeout.&#160;&#160;&#160;&#160;timeout&#160;=&#160;ManualResetEvent.WaitAny(&#160;&#160;&#160;&#160;&#160;&#160;&#160;new&#160;WaitHandle[]&#160;{&#160;waitHandle&#160;},&#160;&#160;&#160;&#160;&#160;&#160;&#160;(int)new&#160;TimeSpan(0,&#160;OPERATION_TIMEOUT,&#160;0).TotalMilliseconds,&#160;&#160;&#160;&#160;&#160;&#160;&#160;false); &#160;&#160;&#160;&#160;if&#160;(timeout&#160;==&#160;ManualResetEvent.WaitTimeout)&#160;&#160;&#160;&#160;{&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&#160;The&#160;operation&#160;timed&#160;out.&#160;Abort&#160;the&#160;operation&#160;thread&#160;or&#160;exit&#160;gracefully.&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Console.WriteLine(&#34;The&#160;operation&#160;timed&#160;out.&#34;);&#160;&#160;&#160;&#160;} &#160;&#160;&#160;&#160;waitHandle.Close();&#160;&#160;&#160;&#160;retryTimer.Dispose();} Let me explain this code section which may look a little convoluted at first. One of the easiest ways of implementing the timeout functionality is using WaitHandles. In the sample above, I have &#8230; <a href="https://blogs.msmvps.com/manoj/2006/11/01/implementing-timeout-retry/" class="more-link">Continue reading Implementing Timeout &#38; Retry</a>]]></description>
										<content:encoded><![CDATA[<p><font color="#330099" face="verdana,geneva">I have come across several situations where I need some sort of Timeout functionality for a particular operation. At the same time, I also needed a provision for retrying the operation a few times before calling quits. I thought about a solution using ManualResetEvent and a Timer which I have outlined below:</font></p>
<div style="background-color: gainsboro;border: black 1px solid;padding: 5px"><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">const&nbsp;int&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">MAX_RETRIES&nbsp;=&nbsp;5;<br /></span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">const&nbsp;int&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">RETRY_INTERVAL&nbsp;=&nbsp;10;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//10&nbsp;seconds<br /></span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">const&nbsp;int&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">OPERATION_TIMEOUT&nbsp;=&nbsp;1;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//1&nbsp;minute</p>
<p></span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">static&nbsp;void&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">DoOperation()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">int&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">retries&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">int&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">timeout&nbsp;=&nbsp;0;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;ManualResetEvent&nbsp;waitHandle&nbsp;=&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">new&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">ManualResetEvent(</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">false</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//Use&nbsp;a&nbsp;timer&nbsp;to&nbsp;retry&nbsp;the&nbsp;opeation&nbsp;periodically<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">Timer&nbsp;retryTimer&nbsp;=&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">null</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">;<br />&nbsp;&nbsp;&nbsp;&nbsp;retryTimer&nbsp;=&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">new&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">Timer(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">new&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">TimerCallback(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//The&nbsp;operation&nbsp;to&nbsp;carry&nbsp;out&nbsp;is&nbsp;represented&nbsp;by&nbsp;this&nbsp;anonymous&nbsp;method.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">delegate</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">(</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">object&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">state)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">try<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">if&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">(retries&nbsp;&gt;&nbsp;0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//The&nbsp;operation&nbsp;has&nbsp;failed&nbsp;before.&nbsp;So&nbsp;you&nbsp;may&nbsp;want&nbsp;to&nbsp;handle&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;that&nbsp;situation&nbsp;here.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">Console.WriteLine(&quot;Retry&nbsp;attempt:&nbsp;{0}&quot;,&nbsp;retries);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//Do&nbsp;the&nbsp;operation&nbsp;which&nbsp;may&nbsp;fail&nbsp;or&nbsp;timeout.&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">Console.WriteLine(&quot;Doing&nbsp;some&nbsp;major&nbsp;operation&nbsp;now.&quot;);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//throw&nbsp;new&nbsp;Exception(&quot;Some&nbsp;exception&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Thread.Sleep(1000);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Checking&nbsp;whether&nbsp;the&nbsp;operation&nbsp;timed&nbsp;out.&nbsp;In&nbsp;this&nbsp;case,&nbsp;the<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;thread&nbsp;isnt&nbsp;forcefully&nbsp;aborted,&nbsp;so&nbsp;you&nbsp;can&nbsp;exit&nbsp;gracefully<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Else,&nbsp;you&nbsp;may&nbsp;need&nbsp;to&nbsp;handle&nbsp;the&nbsp;ThreadAbortException<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">if&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">(timeout&nbsp;==&nbsp;ManualResetEvent.WaitTimeout)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(&quot;It&nbsp;seems&nbsp;that&nbsp;the&nbsp;operation&nbsp;timed&nbsp;out.&nbsp;Need&nbsp;to&nbsp;exit&nbsp;gracefully&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(&quot;Operation&nbsp;completed&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//Set&nbsp;the&nbsp;waithandle&nbsp;if&nbsp;the&nbsp;opeation&nbsp;is&nbsp;successful<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">waitHandle.Set();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//Everything&nbsp;went&nbsp;well.&nbsp;Close&nbsp;the&nbsp;timer.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">retryTimer.Dispose();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">catch&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">(Exception&nbsp;e)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//&nbsp;Handle&nbsp;the&nbsp;exception</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">retries++;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//Check&nbsp;if&nbsp;the&nbsp;number&nbsp;of&nbsp;retries&nbsp;has&nbsp;exceeded&nbsp;the&nbsp;maximum&nbsp;allowed<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">if&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">(retries&nbsp;&gt;&nbsp;MAX_RETRIES)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//Do&nbsp;some&nbsp;logic&nbsp;to&nbsp;handle&nbsp;this&nbsp;situation<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">Console.WriteLine(&quot;Operation&nbsp;has&nbsp;exceeded&nbsp;maximum&nbsp;attempts&quot;);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//&nbsp;Set&nbsp;the&nbsp;waitHandle&nbsp;so&nbsp;that&nbsp;the&nbsp;method&nbsp;returns<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">waitHandle.Set();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//Retry&nbsp;the&nbsp;operation&nbsp;or&nbsp;any&nbsp;do&nbsp;alternative&nbsp;logic&nbsp;here<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">Console.WriteLine(&quot;The&nbsp;operation&nbsp;failed&nbsp;and&nbsp;will&nbsp;be&nbsp;retried&nbsp;in&nbsp;a&nbsp;short&nbsp;while.&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">null</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">new&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">TimeSpan(0,&nbsp;0,&nbsp;0),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">new&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">TimeSpan(0,&nbsp;0,&nbsp;RETRY_INTERVAL));&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//&nbsp;The&nbsp;timer&nbsp;retries&nbsp;the&nbsp;operation&nbsp;for&nbsp;the&nbsp;specified&nbsp;interval</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;//Wait&nbsp;for&nbsp;the&nbsp;operation&nbsp;to&nbsp;complete&nbsp;or&nbsp;timeout.<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">timeout&nbsp;=&nbsp;ManualResetEvent.WaitAny(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">new&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">WaitHandle[]&nbsp;{&nbsp;waitHandle&nbsp;},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">int</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">)</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">new&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">TimeSpan(0,&nbsp;OPERATION_TIMEOUT,&nbsp;0).TotalMilliseconds,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">false</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">if&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">(timeout&nbsp;==&nbsp;ManualResetEvent.WaitTimeout)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//&nbsp;The&nbsp;operation&nbsp;timed&nbsp;out.&nbsp;Abort&nbsp;the&nbsp;operation&nbsp;thread&nbsp;or&nbsp;exit&nbsp;gracefully.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">Console.WriteLine(&quot;The&nbsp;operation&nbsp;timed&nbsp;out.&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;waitHandle.Close();<br />&nbsp;&nbsp;&nbsp;&nbsp;retryTimer.Dispose();<br />}<br /></span></div>
<p><font color="#330099" face="verdana,geneva">Let me explain this code section which may look a little convoluted at first. One of the easiest ways of implementing the timeout functionality is using WaitHandles. In the sample above, I have used a ManualResetEvent, but I guess you may use other WaitHandles like AutoResetEvent** etc, as you see fit. The idea is to spawn off a thread to execute an operation (which could possibly be a long one), and then wait for the thread to signal completion through the ManualResetEvent&rsquo;s Set method. The ManualResetEvent provides a static method called WaitAny which can be used to wait for a specified period of time on one or many waithandles (In our case, it is just one).&nbsp; </font></p>
<p><font color="#330099" face="verdana,geneva">Retry logic can be implemented using a Timer (System.Threading).&nbsp;The Timer event is where the meat of the work is done.&nbsp;The exception handler basically does the work of checking if further retries are required by checking a counter. Once, the process successfully completes, the WaitHandle is Set and the main thread is signaled. &nbsp;</font></p>
<p><font color="#330099" face="verdana,geneva">**At first, it may be difficult to differentiate&nbsp; or choose between ManualResetEvent and AutoResetEvent. AutoResetEvent is analogous to the doorbell switch, which goes back to the off state once you press and release it. AutoResetEvent resets itself automatically once you set it. ManualResetEvent, on the other hand, does not reset automatically &#8211; it is like a normal switch. Therefore, ManualResetEvent can be used when signaling happens once and for all, and subsequently, threads need not wait again for another signal. AutoResetEvent , on the other hand, can be used for finer coordination between threads, when signaling can happen intermittently.</font></p>
<p><font color="#330099" face="verdana,geneva"></p>
<p><font color="#330099" face="verdana,geneva"><em>*Disclaimer: <br />I don&rsquo;t suppose this is the best way to achieve timeout and retry &ndash; this is just one way. Do let me know if there are better techniques!</em></font></p>
<p></font></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2006/11/01/implementing-timeout-retry/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Predicates in Action</title>
		<link>https://blogs.msmvps.com/manoj/2006/08/29/predicates-in-action/</link>
					<comments>https://blogs.msmvps.com/manoj/2006/08/29/predicates-in-action/#comments</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Tue, 29 Aug 2006 02:12:00 +0000</pubDate>
				<category><![CDATA[2343]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2006/08/29/Predicates-in-Action.aspx</guid>

					<description><![CDATA[Generics offer tremendous flexibility &#8211; in more ways than you would ever know. Predicates are a good example for this. .NET 2.0 BCL comes with certain generic delegates &#8211; Action&#60;T&#62;, Predicate&#60;T&#62;, and Converter&#60;Tin, Tout&#62; respectively. Their definitions are given below: public&#160;delegate&#160;TOutput&#160;Converter&#60;TInput,&#160;TOutput&#62;(TInput&#160;input); public&#160;delegate&#160;void&#160;Action&#60;T&#62;(T&#160;obj); public&#160;delegate&#160;bool&#160;Predicate&#60;T&#62;(T&#160;obj); If you look at the definitions, you can guess that the instances of these delegates hold references to methods that do type specific operations. For example, the Predicate delegate represents a method which takes an instance as parameter, and determines if the instance meets a particular criteria. Quite obviously, these delegates would be most applicable to generic &#8230; <a href="https://blogs.msmvps.com/manoj/2006/08/29/predicates-in-action/" class="more-link">Continue reading Predicates in Action</a>]]></description>
										<content:encoded><![CDATA[<p><font color="#000080" face="Verdana" size="2">Generics offer tremendous flexibility &ndash; in more ways than you would ever know. Predicates are a good example for this. .NET 2.0 BCL comes with certain generic delegates &ndash; <strong>Action&lt;T&gt;</strong>, <strong>Predicate&lt;T&gt;</strong>, and <strong>Converter&lt;Tin, Tout&gt; </strong>respectively. Their definitions are given below:</font></p>
<div style="background-color: gainsboro;border: black 1px solid;padding: 5px"><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">public&nbsp;delegate&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">TOutput&nbsp;Converter&lt;TInput,&nbsp;TOutput&gt;(TInput&nbsp;input);</p>
<p></span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">public&nbsp;delegate&nbsp;void&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">Action&lt;T&gt;(T&nbsp;obj);</p>
<p></span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">public&nbsp;delegate&nbsp;bool&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">Predicate&lt;T&gt;(T&nbsp;obj);<br /></span></div>
<p><font color="#000080" face="Verdana" size="2">If you look at the definitions, you can guess that the instances of these delegates hold references to methods that do type specific operations. For example, the Predicate delegate represents a method which takes an instance as parameter, and determines if the instance meets a particular criteria. Quite obviously, these delegates would be most applicable to generic collections and arrays. The List&lt;T&gt; class for instance, employs them&nbsp; in Find, FindAll, Exists, FindIndex, FindLastIndex, ForEach methods. You could find similar usages in the Array class.</font></p>
<p><font color="#000080" face="Verdana" size="2">The real cool thing is using predicates in concert with anonymous methods. At first, it may look convoluted, but actually, that makes coding real easy (and fun). The oversimplified code snippet given below does a couple of things &ndash; given a list of accounts, it finds all accounts with a zero balance, and for each of these accounts sends a mail notifying the same. The FindAll method uses a Predicate&lt;T&gt; delegate and the ForEach delegate employs the Action&lt;T&gt; delegate.</font></p>
<p><font color="#008080"></p>
<div style="background-color: gainsboro;border: black 1px solid;padding: 5px"><span style="font-size: 10pt;color: #000000;font-family: Courier New">List&lt;Account&gt;&nbsp;accounts&nbsp;=&nbsp;GetAllAccounts();<br />accounts.FindAll(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//&nbsp;Uses&nbsp;the&nbsp;Predicate&lt;T&gt;&nbsp;delegate<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">delegate</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">(Account&nbsp;account)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">return&nbsp;</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">(account.Balance&nbsp;==&nbsp;0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;).ForEach<br />&nbsp;&nbsp;&nbsp;&nbsp;(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #008000;font-family: Courier New">//Uses&nbsp;the&nbsp;Action&lt;T&gt;&nbsp;delegate<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 10pt;color: #0000ff;font-family: Courier New">delegate</span><span style="font-size: 10pt;color: #000000;font-family: Courier New">(Account&nbsp;account)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SendMail(account,&nbsp;&quot;Be&nbsp;aware,&nbsp;you&nbsp;now&nbsp;have&nbsp;a&nbsp;zero&nbsp;balance&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;);<br /></span></div>
<p></font></p>
<p><font color="#000080" face="Verdana" size="2">What you may have noticed is that we have completed avoided nested for/foreach loops here. I have used anonymous methods inline here, but you can easily replace them with delegate instances so as to accommodate different criteria or action items at runtime. In more advanced cases, you could generate predicates at runtime based on user provided business rules or something like that.</font></p>
<p><font color="#000080" face="Verdana" size="2">Thus is the amount of flexibility could can reap out of generics! I would strongly recommend one to go over </font><a href="http://msdn.microsoft.com/msdnmag/issues/06/09/AdvancedBasics/"><font color="#0000ff" face="Verdana" size="2"><strong>this interesting MSDN Magazine article</strong></font></a><font color="#000080" face="Verdana" size="2"> on Predicates by Ken Getz to get a better idea.</font></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2006/08/29/predicates-in-action/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Musings on Web 2.0 &#8211; Part 2</title>
		<link>https://blogs.msmvps.com/manoj/2006/07/23/web20part2microformats/</link>
					<comments>https://blogs.msmvps.com/manoj/2006/07/23/web20part2microformats/#respond</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Sun, 23 Jul 2006 15:41:00 +0000</pubDate>
				<category><![CDATA[2341]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2006/07/24/Web20Part2Microformats.aspx</guid>

					<description><![CDATA[In my previous post on Web 2.0, I mentioned that one of the new trends in the web today is that of “mashups”. The idea is about getting data from multiple, disparate sources and collating them in interesting ways. For example, let’s say we need to create a mashup involving a map showing all theatres playing the highest rated (most popular) movie in a particular city. Now, to develop this, one would need several pieces of data from several sources. First of all, you need to use map services (like Google Earth or Virtual Earth) to show a map. Secondly, &#8230; <a href="https://blogs.msmvps.com/manoj/2006/07/23/web20part2microformats/" class="more-link">Continue reading Musings on Web 2.0 &#8211; Part 2</a>]]></description>
										<content:encoded><![CDATA[<p><P><FONT face="Verdana" color="#000080" size="2">In my <A href="/blogs/manoj/archive/2006/05/29/97505.aspx"><STRONG><FONT color="#0000ff">previous post on Web 2.0</FONT></STRONG></A>, I mentioned that one of the new trends in the web today is that of “mashups”. The idea is about getting data from multiple, disparate sources and collating them in interesting ways. For example, let’s say we need to create a mashup involving a map showing all theatres playing the highest rated (most popular) movie in a particular city. Now, to develop this, one would need several pieces of data from several sources. First of all, you need to use map services (like Google Earth or Virtual Earth) to show a map. Secondly, you need a service that lists all popular theatres in a particular city, and what they are currently showing. You would also need ratings and reviews for all the movies that are being screened. Today, all these pieces of information are currently available, but mostly in several different websites. Each of these web sites could have their own revenue model revolving around special services they provide (maybe reviews, for example). So, our mashup which we conceived earlier would receive a setback if there is no data/service available which provides that information in an easily consumable form. In other words, you need structured data to make magic happen.</FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">HTML traditionally, has not been considered as structured data. Perhaps, that is why we have XML to represent complex data forms. But how do you represent information in XML for the web? One answer would be SOAP and Web Services. As revolutionary as web services are for business applications, I feel they are not that conducive to AJAX-based Web 2.0 applications of today. The reason is that SOAP isn’t simple anymore; or at least, for naïve JavaScript-based clients. The evolution of WS-* has morphed SOAP into a monstrous stack of composable standards, which is beyond the reach of simple scripting today. <BR>&nbsp; <BR>So, the order of the day is XML, but in simpler formats, and which are accessible through simpler protocols. Perhaps, this is the reason why RSS and ATOM were born, and are very popular today. Perhaps, this is the reason why REST is gaining momentum. Today, we see a large ecosystem of applications built around <A href="http://en.wikipedia.org/wiki/RSS_%28file_format%29"><STRONG><FONT color="#0000ff">RSS</FONT></STRONG></A> and <A href="http://en.wikipedia.org/wiki/REST"><FONT color="#0000ff"><STRONG>REST</STRONG></FONT></A>, and this can be attributed to their simplicity. </FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">While XML is really powerful, the inherent concern of web applications to incorporate XML to express semantics could seem to be additional investment in time and space. If we go a step backwards towards HTML, and look for ways of expressing semantics, we wouldn’t have an answer, right? Wrong. Apparently, HTML has certain attributes like <EM>rel</EM>, <EM>class</EM>, and <EM>rev</EM> that are rich enough to express, and at the same time could be decoupled from visual markup. This is the idea underpinning a new way of semantic expression on the web – <STRONG><A href="http://en.wikipedia.org/wiki/Microformat"><FONT color="#0000ff">Microformats</FONT></A></STRONG>. Microformats, like RSS, are creating a whole new ecosystem of standards and applications (like crawlers and bots) that make structured data even more pervasive and accessible. </FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">Microformats are a Web 2.0 phenomenon, and are testimonial to what I had to say earlier – Web 2.0 has brought about new &#8220;innovative techniques&#8221; of harnessing existing technology stacks. Be it through XML or Microformats, hopefully, the World Wide Web will evolve into one large blob of structured data available for everyone to create mashups like never before!<BR></FONT></P></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2006/07/23/web20part2microformats/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Musings on Web 2.0</title>
		<link>https://blogs.msmvps.com/manoj/2006/05/28/musings-on-web-2-0/</link>
					<comments>https://blogs.msmvps.com/manoj/2006/05/28/musings-on-web-2-0/#respond</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Sun, 28 May 2006 14:42:00 +0000</pubDate>
				<category><![CDATA[2341]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2006/05/29/97505.aspx</guid>

					<description><![CDATA[Web 2.0 – undoubtedly, is one of the most debated software buzzwords in the recent times. [The other term, in my opinion, which has attracted a lot of debate (and abuse) in the recent history is SOA]. To many, it is just about embracing new techniques, which are DHTML and JavaScript centric. But excavating the early manuscripts of Web 2.0 (like Tim O’Reilly&#8217;s canonical Web 2.0 article) reveals a bigger picture.&#160; So, what exactly is Web 2.0? Here’s another very brief perspective to add to thousand others already existing in different flavors. I would start by putting it this way &#8230; <a href="https://blogs.msmvps.com/manoj/2006/05/28/musings-on-web-2-0/" class="more-link">Continue reading Musings on Web 2.0</a>]]></description>
										<content:encoded><![CDATA[<p><P><FONT face="Verdana" color="#000080" size="2">Web 2.0 – undoubtedly, is one of the most debated software buzzwords in the recent times. [The other term, in my opinion, which has attracted a lot of debate (and abuse) in the recent history is SOA]. To many, it is just about embracing new techniques, which are DHTML and JavaScript centric. But excavating the early manuscripts of Web 2.0 (like <A href="http://www.oreillynet.com/pub/a/oreilly/tim/news/2005/09/30/what-is-web-20.html">Tim O’Reilly&#8217;s canonical Web 2.0 article</A>) reveals a bigger picture.&nbsp; </FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">So, what exactly is Web 2.0? Here’s another very brief perspective to add to thousand others already existing in different flavors. I would start by putting it this way (the world’s smallest definition of Web 2.0): A set of <U><STRONG>new ideologies</STRONG></U> combined with a set of <U><STRONG>novel techniques</STRONG></U> for building today’s web applications. Another definition could simply be – a new ecosystem of applications (or say “services”) built on the WWW platform.</FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2"><STRONG>The new ideologies:</STRONG></FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">1) The Web Platform</FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">Websites today are not just places where static information is presented, or which offer a single service (like e-mail, storage, forums etc). Websites today are platforms in their own right. They offer the capability to “compose” disparate applications to build a very powerful whole. The word “Mash-Up” is a popular term used to represent this ideology of mixing (or re-mixing) data and functionality. Now, part of this realization is capable by seeing our large world of applications as services, which can be consumed in non-proprietary ways. Not just SOAP, but plain old JavaScript itself is turning out to be that duct-tape technology making this possible. Live, Google and PageFlakes are great examples of the same.</FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">2) De-centralization of the Authority &amp; Data</FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">Websites of the past era basically owned the content and its presentation entirely. With Web 2.0, the authority on the source of the data and its presentation shifts to the user. The website or web application basically provides a canvas which the user leverages to consume (and compose) services from disparate sources to meet their needs. As an example, you could cite msn.com (of the yester years) giving way to Live.com of today.</FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">3) Collaboration</FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">This is new trend to surface in recent past. Websites today are opening the doors to the world to participate, contribute and collaborate. In this model, users directly contribute to the data/knowledge base of the website. The exemplar of this ideology is “Wiki”s, and Wikipedia, which is one of the most popular websites today. Tim O’Reilly’s article rightly calls this “Harnessing Collective Intelligence”.</FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2"><STRONG>The Novel Techniques:</STRONG></FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">HTTP, DHTML, JavaScript haven’t changed much in the recent times. But these days, you get to here a lot of new jargons popping all over the place, all of these based of these fundamental technologies. At the lead of this jargon parade is AJAX (Asynchronous JavaScript and XML). Some others in this list are Comet, JSON, etc. An extensive examination of these would reveal that these are nothing but simple tweaks and hacks to existing methodologies like XMLHTTP and JavaScript’s own <EM>eval</EM> function. Therefore, I term these seemingly “new technologies” as novel techniques.&nbsp; </FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">New or otherwise, these techniques and ideologies definitely have resulted in new possibilities and opportunities for web application developers. We are seeing new revenue models which transcend the notion of simple buying and selling which we saw in the recent past. A new journey has just begun, it is time for us to get on the bus and be a part a long adventure!</FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2"></FONT>&nbsp;</P></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2006/05/28/musings-on-web-2-0/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Tip: Debugging Windows Services</title>
		<link>https://blogs.msmvps.com/manoj/2006/04/03/tip-debugging-windows-services/</link>
					<comments>https://blogs.msmvps.com/manoj/2006/04/03/tip-debugging-windows-services/#respond</comments>
		
		<dc:creator><![CDATA[manoj]]></dc:creator>
		<pubDate>Mon, 03 Apr 2006 13:25:00 +0000</pubDate>
				<category><![CDATA[2343]]></category>
		<guid isPermaLink="false">/blogs/manoj/archive/2006/04/04/89042.aspx</guid>

					<description><![CDATA[The other day, I was watching the PDC presentations on WCF and one of them was on hosting WCF services by Steve Maine. Part of the presentation was about hosting Indigo on Windows services (or NT Services). One of the demos had a small and very interesting tip on debugging service startup, which I shall try to elaborate here. I always wondered how the service startup code could be debugged. There are two problems which you would face invariably. First of all, there is no process to which you can attach a debugger to start with. I have done stupid &#8230; <a href="https://blogs.msmvps.com/manoj/2006/04/03/tip-debugging-windows-services/" class="more-link">Continue reading Tip: Debugging Windows Services</a>]]></description>
										<content:encoded><![CDATA[<p><P><FONT face="Verdana" color="#000080" size="2">The other day, I was watching the PDC presentations on WCF and one of them was on hosting WCF services by Steve Maine. Part of the presentation was about hosting Indigo on Windows services (or NT Services). One of the demos had a small and very interesting tip on debugging service startup, which I shall try to elaborate here. </FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">I always wondered how the service startup code could be debugged. There are two problems which you would face invariably. First of all, there is no process to which you can attach a debugger to start with. I have done stupid things in the past to step into startup code &#8211; by adding a Thread.Sleep in the OnStart method, assuming that this would give me enough time to attach the debugger to the newly started process. This isn’t very smart as you would hit the second problem – the Service Controller Manager (SCM) would time the service out way too soon. Not to worry much &#8211; there is any elegant solution to both these problems. </FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">You need not add a Thread.Sleep anymore – just add a Debugger.Break in your code. This isn’t new, but I simply hadn’t found a use for this before. This method is actually pretty useful if you want to conditionally attach the debugger in situations like this. </FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">The solution to the problem of the SCM timing out is a method in the ServiceBase class (System.ServiceProcess) that has been added in .NET 2.0. This method is the <STRONG>RequestAdditionalTime</STRONG>, which takes a single parameter – the amount of time in milliseconds that the SCM has to wait additionally before pulling the plug on the service. Note that this method can only be called inside of OnStart, OnPause, OnContinue and OnStop (basically all the commands you can forward to the SCM). </FONT></P><br />
<P><FONT face="Verdana" color="#000080" size="2">Neat!</FONT></P></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogs.msmvps.com/manoj/2006/04/03/tip-debugging-windows-services/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
