<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Questions you should ask before using a callback / delegate</title><link>http://blogs.msdn.com/b/jmstall/archive/2006/10/14/callbacks_5F00_are_5F00_dangerous.aspx</link><description>I just got burned by using callbacks in a multi-threaded app. I've rewritten the part to avoid callbacks, but for my good-deed-of-the-day, I wanted to issue a word of warning. 
 Before you can safely use a callback / delegate / virtual function, particularly</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>re: Questions you should ask before using a callback / delegate</title><link>http://blogs.msdn.com/b/jmstall/archive/2006/10/14/callbacks_5F00_are_5F00_dangerous.aspx#833614</link><pubDate>Tue, 17 Oct 2006 07:39:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:833614</guid><dc:creator>Mike Stall - MSFT</dc:creator><description>&lt;p&gt;David - those are great defensive rules.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=833614" width="1" height="1"&gt;</description></item><item><title>re: Questions you should ask before using a callback / delegate</title><link>http://blogs.msdn.com/b/jmstall/archive/2006/10/14/callbacks_5F00_are_5F00_dangerous.aspx#833238</link><pubDate>Tue, 17 Oct 2006 02:37:43 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:833238</guid><dc:creator>David Levine</dc:creator><description>&lt;p&gt;These are all very valuable questions that devs should ask when designing and implementing a callback of any type (delegates are one type).&lt;/p&gt;
&lt;p&gt;I try to never make assumptions about what the callee will do in the callback. I assume that some piece of code somewhere will abuse the callback and leave me to try to pick up the pieces, so I try to program as defensively as possible. Many of my &amp;quot;golden rules&amp;quot; are similar to yours. This means...&lt;/p&gt;
&lt;p&gt;1. All callbacks must be rentrant or handle reentrancy issues. For example, I always assume that a call to initiate another operation can occur within a completion routine.&lt;/p&gt;
&lt;p&gt;2. I never call the callback with locks held. I've not run into a case where I needed to hold a lock - I've redesigned a few components to remove the need.&lt;/p&gt;
&lt;p&gt;3. Always assume the callee will cause an error condition....so wrap your callback in a try-catch handler with suitable and well-defined error semantics (ignore/swallow, propagate, rethrow, crash, etc). &lt;/p&gt;
&lt;p&gt;Associated questions are: if one callback raises an error how will that affect other subscribers to an event or callback? Does it cancel it? Abort it?&lt;/p&gt;
&lt;p&gt;Are errors saved and reported elsewhere? Discarded? Logged? Traced?&lt;/p&gt;
&lt;p&gt;4. Make no assumptions about thread state on return. Priorities may have changed, security contexts may be different, etc. This is similar to your example about static variables - it is state shared across instances. If global state is altered how should the caller react?&lt;/p&gt;
&lt;p&gt;5. Make no assumptions about how long it will take the callee to complete and return, or what they will do in the callback routine. Also consider using asynchronous versus synchronous callback mechanisms - this may avoid running into some deadlock problems, especially when calling back into a UI thread.&lt;/p&gt;
&lt;p&gt;6. I consider calling back using the original caller's synchronization context - this helps in situations where some callbacks occur on non-UI threads while others occur on UI threads. If its a UI thread I generally prefer to use async callbacks.&lt;/p&gt;
&lt;p&gt;If you must constrain what the callback is allowed to do then it should be part of the intellisense documentation and well documented elsewhere so that devs that are otherwise unfamiliar with your component will have as good a chance as possible of understanding and programming against those constraints. &lt;/p&gt;
&lt;p&gt;It would be nice if somehow the component itself could enforce the constraints that callbacks must adhere to, but I think we are lightyears away from such an environment.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=833238" width="1" height="1"&gt;</description></item><item><title>re: Questions you should ask before using a callback / delegate</title><link>http://blogs.msdn.com/b/jmstall/archive/2006/10/14/callbacks_5F00_are_5F00_dangerous.aspx#830429</link><pubDate>Mon, 16 Oct 2006 06:17:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:830429</guid><dc:creator>Kent Boogaart</dc:creator><description>&lt;p&gt;Great post. Regarding the locking issues, I would argue that never taking a lock on a publicly accessible object is a good thing. If you need to share a lock amongst objects then you can expose a property / method to get / take the lock. That way you can control access to the lock.&lt;/p&gt;
&lt;p&gt;I have long thought that .NET repeated a mistake made by platforms before it by allowing arbitrary locking on any object. IMHO, locks should only be permitted on a special purpose Lock struct / class. This would encourage encapsulation of locks and would have the added benefit of reducing the overhead associated with each object on the managed heap.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=830429" width="1" height="1"&gt;</description></item><item><title>Interesting Finds: October 14, 2006</title><link>http://blogs.msdn.com/b/jmstall/archive/2006/10/14/callbacks_5F00_are_5F00_dangerous.aspx#826496</link><pubDate>Sat, 14 Oct 2006 23:29:55 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:826496</guid><dc:creator>Jason Haley</dc:creator><description>&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=826496" width="1" height="1"&gt;</description></item><item><title>re: Questions you should ask before using a callback / delegate</title><link>http://blogs.msdn.com/b/jmstall/archive/2006/10/14/callbacks_5F00_are_5F00_dangerous.aspx#825233</link><pubDate>Sat, 14 Oct 2006 17:18:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:825233</guid><dc:creator>Peter Ritchie</dc:creator><description>&lt;p&gt;Great post.&lt;/p&gt;
&lt;p&gt;There's a thread on MSDN Forums that exemplifies another problem using asynchronous delegates when implicitly multithreaded: &lt;a rel="nofollow" target="_new" href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=678862&amp;amp;SiteID=1"&gt;http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=678862&amp;amp;SiteID=1&lt;/a&gt;. &amp;nbsp;The gist is (one that you didn't mention) don't call Event-based Asynchronous Pattern asynchronous methods from an asynchronous delegate.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=825233" width="1" height="1"&gt;</description></item></channel></rss>