Channels ▼

Arnon Rotem-Gal-Oz

Dr. Dobb's Bloggers

Exception Guidelines vs. Concurrency

January 13, 2009

A couple of days ago, one of our team members saw in the log that we are getting index out of bound exceptions in some of the code of the a piece of code I wrote (part of the EventBroker). Taking a look he saw the following:

<span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px">       <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">private</span> <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">void</span> EventSender(<span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">object</span> state)<br />        {<br />            var id <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px">=</span> (Guid) state;<br />            <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">try</span><br />            {<br />                    sagas[id].Dispatch();<br />            }<br />            <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">catch</span> (Exception e)<br />            {<br />               </span><br /><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px">                Logger.DebugFormat(<span style="color: #666666; background-color: #e4e4e4; font-family: Courier New; font-size: 11px">"EventSender: Exeption Details={0}"</span>,e);</span><br /><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px">                rwl.TryRLock();<br />                var isClosed <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px">=</span> true;<br />                <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">if</span> (sagas.ContainsKey(id))<br />                    isClosed <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px">=</span> sagas[id].IsClosed;<br />                rwl.ExitReadLock();<br /><br />                <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">if</span> (!isClosed)<br />                    HandleSagaFault(id);<br />                <br />            }<br />        }</span>

It is well known that one of the guidelines for exception throwing is "Do not use exceptions for normal or expected errors, or for normal flow of control".So,naturally, he raised an eyebrow and asked me why don't I check that the id exist before I try to call the Dispatch method.
e.g. something like:
<span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px"><span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">            try</span><br />            {</span><br /><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px">                rwl.TryRLock();<br />                var isClosed <span style="color: Red; background-color: transparent; font-family: Courier New; font-size: 11px">=</span> true;<br />                <span style="color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px">if</span> (sagas.ContainsKey(id))</span><br /><span style="color: Black; background-color: transparent; font-family: Courier New; font-size: 11px">                    sagas[id].Dispatch();<br />                rwl.ExitReadLock();<br />            }</span>

Well, as it happens the EventSender method runs on a thread pool thread (something you could have guessed from the object State parameter). It's role is to get the saga to dissipate the event. i.e. the Dispatch method on the Saga object handles actually sending   events to event's subscribers.And while it does its work in parallel it also waits for all the events to arrive before returning (collecting any communications exceptions etc.) What this means is that the Dispatch method takes awhile to return.

Ahh, there's the rub - Contrary to the guideline mentioned above, it is actually more worthwhile to pay the performance penalty of throwing an exception rather than pay the more severe penalty of holding a lock for a long time. The lock affects all the threads running whereas the exception only affects the isolated thread.

Indeed - on another MSDN page there a better version of the guideline "Do not use exceptions for normal flow of control, if possible. Except for system failures and operations with potential race conditions"

The lesson here is (again) is that we need to think before blindly following guidelines.Guidelines are, well er, guidelines not commandments

PS
if you release the lock before calling Dispatch you don't gain anything, since it is multi-threaded code and the id can still be collected between the check and the call itself.

PPS
in case you are wondering TryRLock() is an extension method which try to obtain a lock with a given (short) timeout and throw (instead of deadlock) if the timeout is reached.

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video