<?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>Lab49 Blog &#187; Mike Davey</title>
	<atom:link href="http://blog.lab49.com/archives/author/mike/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.lab49.com</link>
	<description>Technology and industry insights from Lab49.</description>
	<lastBuildDate>Sat, 04 Sep 2010 16:42:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Safe to Remove Now?</title>
		<link>http://blog.lab49.com/archives/228</link>
		<comments>http://blog.lab49.com/archives/228#comments</comments>
		<pubDate>Tue, 21 Mar 2006 16:29:24 +0000</pubDate>
		<dc:creator>Mike Davey</dc:creator>
				<category><![CDATA[.Net]]></category>

		<guid isPermaLink="false">http://blog.lab49.com/?p=228</guid>
		<description><![CDATA[private void button1_Click(object sender, System.EventArgs e)
{
           DoItOnce();
           button1.Click-=new EventHandler(button1_Click);
}
If you think about it for  a second, the above code is a little trickier than it appears at first. Something somewhere is traversing an array [...]]]></description>
			<content:encoded><![CDATA[<p><code>private void button1_Click(object sender, System.EventArgs e)<br />
{<br />
           DoItOnce();<br />
           button1.Click-=new EventHandler(button1_Click);</p>
<p>}</code></p>
<p>If you think about it for  a second, the above code is a little trickier than it appears at first. Something somewhere is traversing an array of delegates and invoking each one. The invocation of this particular delegate removes the delegate from the array. Removing items from arrays that you are currently iterating through can, if handled carelessly, cause problems, no? Nonetheless, if MS had been so careless in coding the framework as to give rise to those sorts of problems, you wouldn&#8217;t trust them to .. I dunno.. collect your garbage much less any of the fancy computer stuff you count on the them for.</p>
<p>So with that faith in heart you come to<a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.application.addmessagefilter(VS.80).aspx"> Application.AddMessageFilter</a>. This method allows you supposedly to get a crack at all messages posted to your app&#8217;s message loop. ( I say supposedly because all I&#8217;ve ever seemed to be able to get out of it are keyboard and mouseevents. But maybe that&#8217;s just me.) Whatever it is doing it must be working somewhat like the event sink: it&#8217;s going through the list of registered PreFilterMessage delegates and calling them. But what if you do this:</p>
<p><code>public bool PreFilterMessage(ref Message msg)<br />
			{<br />
				if(_quit)<br />
					Application.RemoveMessageFilter(this);<br />
				return false;<br />
			}</code></p>
<p>The answer is that if you&#8217;ve got any other IMessageFilter&#8217;s listening to this app, you&#8217;re dead, with the epitaph:</p>
<blockquote><p>An unhandled exception of type &#8216;System.ArgumentOutOfRangeException&#8217; occurred in mscorlib.dll</p>
<p>Additional information: Index was out of range.  Must be non-negative and less than the size of the collection.</p></blockquote>
<p>Very disappointing. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lab49.com/archives/228/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The trouble with Doubles</title>
		<link>http://blog.lab49.com/archives/214</link>
		<comments>http://blog.lab49.com/archives/214#comments</comments>
		<pubDate>Mon, 06 Feb 2006 20:51:32 +0000</pubDate>
		<dc:creator>Mike Davey</dc:creator>
				<category><![CDATA[.Net]]></category>

		<guid isPermaLink="false">http://blog.lab49.com/?p=214</guid>
		<description><![CDATA[If you&#8217;ve ever wondered why many developers recommend you ALWAYS use the slow, heavy Decimal type, rather than Double when doing financials, check this out:

In our production environment we&#8217;ve gotten occasional bugs that could only be the result of double.Equals failing and, as you can see, this can actually happen. .Net optimizes double performance by [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever wondered why many developers recommend you ALWAYS use the slow, heavy Decimal type, rather than Double when doing financials, check this out:</p>
<p><img src='/wp-content/watch.jpg' alt='Watching Doubles' /></p>
<p>In our production environment we&#8217;ve gotten occasional bugs that could only be the result of double.Equals failing and, as you can see, this can actually happen. .Net optimizes double performance by taking advatage of the extended floating point facilities of the processor. Thus operations done in cpu cache may be done with a higher precision than that supported by System.Double. So when you get to a point where a comparison occurs between a number in cache and one in memory, even if they were the result of the same operation, the may not be actually equal.</p>
<p>Unless you absolutely can&#8217;t stand the <a href="http://wesnerm.blogs.com/net_undocumented/2004/03/decimal_perform.html">performance hit</a>,  I would recommend using System.Decimal for operations that rely on a single standard of precision across all operations. </p>
<p>For more on the pitfalls of .Net floating point math go <a href="http://wesnerm.blogs.com/net_undocumented/2005/01/floating_point__1.html">here</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lab49.com/archives/214/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>This MessageBox is Brought to You By Budweiser</title>
		<link>http://blog.lab49.com/archives/167</link>
		<comments>http://blog.lab49.com/archives/167#comments</comments>
		<pubDate>Tue, 15 Nov 2005 15:07:01 +0000</pubDate>
		<dc:creator>Mike Davey</dc:creator>
				<category><![CDATA[General Development]]></category>

		<guid isPermaLink="false">http://blog.lab49.com/?p=167</guid>
		<description><![CDATA[Not being a religious person myself, I tend to take a skeptical, detached view of the various Google vs Microsoft vs Apple vs OSS fatwahs that fill the tech blog world. (Although I am pretty certain that if the Devil had a motto, it would be "Dont Be Evil".) Nonetheless, the past week's combination of leaks ( the <a href="http://www.businessweek.com/technology/content/nov2005/ms_memo/ms_memo_bill.htm">Bill Gates memo </a>and the <a href="http://www.businessweek.com/technology/content/nov2005/ms_memo/ms_memo_ozzie.htm">Ray Ozzie memo</a>) and <a href="http://www.pcworld.com/news/article/0,aid,123364,00.asp">announcements</a> from MS were a minor epiphany.  Not so much that "Software is Dead", but that nobody is really interested in discussing whether or not this is a good thing.

As developers and good Americans of course we're all in  love with Google. Avoiding Evil is one thing,....]]></description>
			<content:encoded><![CDATA[<p>Not being a religious person myself, I tend to take a skeptical, detached view of the various Google vs Microsoft vs Apple vs OSS fatwahs that fill the tech blog world. (Although I am pretty certain that if the Devil had a motto, it would be &#8220;Dont Be Evil&#8221;.) Nonetheless, the past week&#8217;s combination of leaks ( the <a href="http://www.businessweek.com/technology/content/nov2005/ms_memo/ms_memo_bill.htm">Bill Gates memo </a>and the <a href="http://www.businessweek.com/technology/content/nov2005/ms_memo/ms_memo_ozzie.htm">Ray Ozzie memo</a>) and <a href="http://www.pcworld.com/news/article/0,aid,123364,00.asp">announcements</a> from MS were a minor epiphany.  Not so much that &#8220;Software is Dead&#8221;, but that nobody is really interested in discussing whether or not this is a good thing.</p>
<p>As developers and good Americans of course we&#8217;re all in  love with Google. Avoiding Evil is one thing, but they&#8217;ve also managed to stay away from Stupid pretty well, too.  I&#8217;m a huge fan. But over the summer, when the business pages began to trumpet them as &#8220;The World&#8217;s Largest Media Company&#8221;, it sounded odd. Not only were they extraordinarily  successful while giving me so much great stuff for free (Isn&#8217;t laying Golden Eggs supposed to be a terminal condition? ), but it also seems that they had gotten into the <em>advertsing</em> business on the side! Just as something like Google Maps realized a technological potential most of us had forgotten ever existed, they similarly resurrected the idea that you could make a lot of money on the internet by providing free services. Obviously, for those who see Google as the last best hope to make Bill Gates pay for his sins, their success is a vindication of good software and responsible business practices.</p>
<p>So what is the number one lesson Google&#8217;s main competitor has learned from this? Now that all the chairs have been thrown, and all the really really smart people are eating Microsoft&#8217;s lunch for free in the enemy&#8217;s cafeteria, what is the nature of this &#8220;adapt-or-die&#8221; change to the software world? <a href="http://www.businessweek.com/technology/content/nov2005/ms_memo/ms_memo_ozzie.htm">Quote</a>:</p>
<blockquote><p>Today there are three key tenets that are driving fundamental shifts in the landscape – all of which are related in some way to services.  It&#8217;s key to embrace these tenets within the context of our products and services.<br />
<strong>1.     The power of the advertising-supported economic model.</strong><br />
Online advertising has emerged as a significant new means by which to directly and indirectly fund the creation and delivery of software and services.  In some cases, it may be possible for one to obtain more revenue through the advertising model than through a traditional licensing model.  Only in its earliest stages, no one yet knows the limits of what categories of hardware, software and services, in what markets, will ultimately be funded through this model.  And no one yet knows how much of the world&#8217;s online advertising revenues should or will flow to large software and service providers, medium sized or tail providers, or even users themselves.</p></blockquote>
<p>The other two items on Ozzie&#8217;s list ( &#8220;The effectiveness of a new delivery and adoption model&#8221; and &#8220;The demand for compelling, integrated user experiences that &#8216;just work&#8217;) strike me as filler. The scare quotes around &#8220;just work&#8221; don&#8217;t make it seem any less awkward then it did the first time around. But for the first time working in this industry, I finally understand what services is: it&#8217;s the kind of software that can sell things to the user. It&#8217;s advertising.</p>
<p>I am by no means trying to say that advertising is by definition a bad thing. Some of my favorite things are brought to me by the good people at wherever. But if MS is in fact now committed to an advertising-based model, it&#8217;s fair to say that the momentum of this change to the software business is unstoppable and I think we (i.e. people who like computers and the internet) might want to go into this with our eyes wide open. It&#8217;s kind of scary that the leading edge of the discussion on what these changes may mean is going on in Redmond&#8217;s Exchange Server. </p>
<p>One question I&#8217;d like to hear asked is <em>Will this make software better? </em> Even if we&#8217;re able to meet the technical constraints posed by a Strong Server/Weak Client architecture, the fact is that user needs will now have to share resources with the needs of the customer paying the bills.  If experience is any guide, the first vicitm of such a change would be a certain level  &#8220;freindly hackability&#8221;  that so many of us geeks hold dear in our favorite apps. We have seen what the current IP zeitgeist has wrought on stuff you thought you owned, imagine when you&#8217;re simply a guest of the Disney Corporation. Next time you&#8217;re at Space Mountain, ask them if you can drive. Also, for the past twenty years or so, vertical consolidation of media companies has been somewhat offset by the existence of the internet as a frontier of cheap production and distribution. What will be the consequences if the software industry now becomes officially part of the chain?  How difficult, for example, will it be,  a couple of tech generations down the road,  to publish your own site without using a branded service?</p>
<p>Along with rich web apps and sacks of money, perhaps another of the dot com era&#8217;s internet visions is finally coming to pass at the moment we least  expect it. The convergence of TV and PC. Yikes.</p>
<p>It&#8217;s almost enough to make you glad there&#8217;s Open Source.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lab49.com/archives/167/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Control.Invoke Gotcha</title>
		<link>http://blog.lab49.com/archives/154</link>
		<comments>http://blog.lab49.com/archives/154#comments</comments>
		<pubDate>Tue, 25 Oct 2005 17:24:33 +0000</pubDate>
		<dc:creator>Mike Davey</dc:creator>
				<category><![CDATA[.Net]]></category>

		<guid isPermaLink="false">http://blog.lab49.com/?p=154</guid>
		<description><![CDATA[I recently stumbled (of course) across an interesting wrinkle in Control.Invoke/BeginInvoke. From the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwindowsformscontrolclassinvoketopic2.asp">fine print</a>:

<em>The [invoked] delegate can be an instance of EventHandler, in which case the sender parameter will contain this control, and the event parameter will contain EventArgs.Empty.</em>

I dunno... While this seems to be done in order to preserve the notion of  "sender" in an eventhandler, this strikes me as a somewhat shady clause to Invokes contract. ]]></description>
			<content:encoded><![CDATA[<p>I recently stumbled (of course) across an interesting wrinkle in Control.Invoke/BeginInvoke. From the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwindowsformscontrolclassinvoketopic2.asp">fine print</a>:</p>
<p> <em>The</em> [invoked] <em>delegate can be an instance of EventHandler, in which case the sender parameter will contain this control, and the event parameter will contain EventArgs.Empty.</em></p>
<p>I dunno&#8230; While this seems to be done in order to preserve the notion of  &#8220;sender&#8221; in an eventhandler, this strikes me as a somewhat shady clause to Invoke&#8217;s contract. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lab49.com/archives/154/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WindowsFormsParkingWindow</title>
		<link>http://blog.lab49.com/archives/138</link>
		<comments>http://blog.lab49.com/archives/138#comments</comments>
		<pubDate>Mon, 03 Oct 2005 16:09:07 +0000</pubDate>
		<dc:creator>Mike Davey</dc:creator>
				<category><![CDATA[.Net]]></category>

		<guid isPermaLink="false">http://blog.lab49.com/?p=138</guid>
		<description><![CDATA[I recently had to deal with a truly delightful bug in a Winforms app I was working on: Immediately after being clicked on, the main window would  become deactivated.  As my last step before calling in an exorcist, I logged WM_ACTIVATE to see if I could find the identity of the form that was being activated when this happened.  Turns out I was being hijacked by something called the <a href="http://dotnet.org.za/johannds/archive/2004/03/08/650.aspx">WindowsFormsParkingWindow</a>.

The WindowsFormsParkingWindow is an orphanage for unwanted Child Controls. When you remove a Control from your form, it gets....er...parked on the WindowFormsParkingWindow. Evidently, if the removed control has focus when this happens, you've got a problem because the WindowsFormsParkingWindow, i.e. the Invisible, Modal (!) WindowsFormsParkingWindow, will now become active in a way nature never intended. 

To avoid this, make sure you do not remove a child control while it has focus.]]></description>
			<content:encoded><![CDATA[<p>I recently had to deal with a truly delightful bug in a Winforms app I was working on: Immediately after being clicked on, the main window would  become deactivated.  As my last step before calling in an exorcist, I logged WM_ACTIVATE to see if I could find the identity of the form that was being activated when this happened.  Turns out I was being hijacked by something called the <a href="http://dotnet.org.za/johannds/archive/2004/03/08/650.aspx">WindowsFormsParkingWindow</a>.</p>
<p>The WindowsFormsParkingWindow is an orphanage for unwanted Child Controls. When you remove a Control from your form, it gets&#8230;.er&#8230;parked on the WindowFormsParkingWindow. Evidently, if the removed control has focus when this happens, you&#8217;ve got a problem because the WindowsFormsParkingWindow, i.e. the Invisible, Modal (!) WindowsFormsParkingWindow, will now become active in a way nature never intended. </p>
<p>To avoid this, make sure you do not remove a child control while it has focus.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lab49.com/archives/138/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>InvokeRequired not required</title>
		<link>http://blog.lab49.com/archives/87</link>
		<comments>http://blog.lab49.com/archives/87#comments</comments>
		<pubDate>Thu, 08 Sep 2005 21:09:48 +0000</pubDate>
		<dc:creator>Mike Davey</dc:creator>
				<category><![CDATA[.Net]]></category>

		<guid isPermaLink="false">http://daniel.lab49.com/wordpress/?p=87</guid>
		<description><![CDATA[One of the more questionable patterns in .Net Windows Forms programming is the following sort of thing:
            private void OnDataChanged(object sender, EventArgs e)
      {
            if(InvokeRequired)
    [...]]]></description>
			<content:encoded><![CDATA[<p>One of the more questionable patterns in .Net Windows Forms programming is the following sort of thing:</p>
<p>            private void OnDataChanged(object sender, EventArgs e)<br />
      {<br />
            if(InvokeRequired)</p>
<p>                  BeginInvoke(new EventHandler(OnDataChanged), new object[] { sender, e });</p>
<p>            else<br />
            {<br />
                  &#8230;&#8230;<br />
            }<br />
      }</p>
<p>Maybe it&#8217;s just me, but having to say &#8220;Please do whatever you need to do before you do what I&#8217;m about to tell you to do&#8221; each and every time I tell someone to do something makes me tired. On a recent project I worked on, we developed a handy strategy to avoid just this.</p>
<p>The key to this solution is the Windows User32 function PostMessage, which will allow you to put a message into the application&#8217;s message queue. That message will by definition, wind up received on the GUI thread. All you need is something that will listen, and means for it fire your delegate. A message only window?</p>
<p>Message-Only Windows</p>
<p>A message-only window enables you to send and receive messages. It is not visible, has no z-order, cannot be enumerated, and does not receive broadcast messages. The window simply dispatches messages.</p>
<p>To create a message-only window, specify the HWND_MESSAGE constant or a handle to an existing message-only window in the hWndParent parameter of the CreateWindowEx function. You can also change an existing window to a message-only window by specifying HWND_MESSAGE in the hWndNewParent parameter of the SetParent function.</p>
<p>Our MessageWindow is then wrapped with a queue, to form a Dispatcher, whose job it is to place the delegate to be fired onto the queue and post a message to the MessageWindow, who will take it out and fire it. The last thing we need is some sort of facade or proxy for our original delegate that will allow it be invoked in such a roundabout manner.</p>
<p>The first step is to define an interface that our Dispatcher will use to invoke the the underlying delegate. Let&#8217;s call it STAInvoke (for Single Threaded Apartment, the threading model employed by windows forms that made all this necessary in the first place.)<br />
 <span id="more-87"></span><br />
Our DelegateProxy class has the following responsibilities: </p>
<p>            &#8212; Put messages onto the Dispatcher when invoked.</p>
<p>            &#8212; Wrap the original delegate and call DynamicInvoke on it once we are in the right thread</p>
<p>            &#8212; Provide a factory with which you can dispense Delegates derived from proxies</p>
<p>The factory code looks something like this (minus exception handling):</p>
<p>public static Delegate CreateDelegate(Delegate dlgt)</p>
<p>{</p>
<p>      DelegateProxy proxy = new DelegateProxy(dlgt,Thread.CurrentThread.ApartmentState == ApartmentState.STA);</p>
<p>      Delegate contextdlgt = null;</p>
<p>      contextdlgt = Delegate.CreateDelegate(dlgt.GetType(), proxy, &#8220;Invoke&#8221;);</p>
<p>      return contextdlgt;</p>
<p>}</p>
<p>However there is some unpleasantness here. (Let&#8217;s call it a long-standing TODO.) The Invoke method on the proxy must have the same signature as your original delegate. Thus for each unique signature in the application with which you would like to use this class, you need an corresponding overload of Invoke in DelegateProxy.</p>
<p>So how do you use this? Let&#8217;s say your FooService has a single event, Changed, of type EventHandler. A slight modification of the usual plumbing for attaching events gives you this:</p>
<p>            public event EventHander Changed</p>
<p>            {</p>
<p>                        add</p>
<p>                        {</p>
<p>                                    _changed += (EventHandler)STADelegate.CreateDelegate(value)</p>
<p>                        }</p>
<p>                        remove</p>
<p>                        {</p>
<p>                                    _changed -= (EventHandler)STADelegate.CreateDelegate(value)</p>
<p>                        }</p>
<p>            }</p>
<p>When _changed is fired then, the Invoke method of the DelegateProxy is actually called. This then looks to see if it was orginally created on the GUI thread. If it was not, it simply invokes the original delegate. If it was, it then puts itself onto the queue of the Dispatcher and posts a message into the message queue. When that message is recieved, safely in the GUI thread, the dispatcher removes the DelegateProxy from its queue and calls that DelegateProxy’s STAInvoke method.</p>
<p>If you feel this is a long way to go to replace a little if statement, I (sort of) understand. For me, if(InvokeRequired)  BeginInvoke, sounds like some sort of obsessive-compulsive tick, rather than effective use of language. If I’d wanted to have to say things like that all day, I’d have become a lawyer.</p>
<p><strong>SourceCode;</strong></p>
<p>using System;<br />
using System.Runtime.InteropServices;<br />
using System.Windows.Forms;</p>
<p>namespace Lab49.Utils<br />
{<br />
	/// <summary><br />
	/// Summary description for User32.<br />
	/// </summary><br />
	public class User32<br />
	{<br />
		/// <summary><br />
		/// The base id for user-defines messages; max = 0&#215;7FFF<br />
		/// </summary><br />
		public const int WM_USER= 0&#215;0400;<br />
		/// <summary><br />
		/// When assigned to parent, makes window a message-only window<br />
		/// </summary><br />
		public const int HWND_MESSAGE= -3;</p>
<p>		/// <summary><br />
		/// Nonclient Create message<br />
		/// </summary><br />
		public const int WM_NCCREATE = 0&#215;0081;</p>
<p>		/// <summary><br />
		/// Creates a unique User Message<br />
		/// </summary><br />
		[DllImport("user32.dll")]<br />
		public static extern uint RegisterUserMessage(string msgName);</p>
<p>		/// <summary><br />
		/// Post a message to the queue of hWnd<br />
		/// </summary><br />
		[DllImport("user32.dll")]<br />
		public static extern bool PostMessage(IntPtr hWnd, uint msg, int wP, int lP);</p>
<p>		/// <summary><br />
		/// Post a message to the queue of ThreadID<br />
		/// </summary><br />
		[DllImport("user32.dll")]<br />
		public static extern bool PostThreadMessage(int ThreadID, uint msg, int wP, int lP);</p>
<p>	}<br />
	public class MessageWindow: NativeWindow, IDisposable<br />
	{</p>
<p>		public MessageWindow(): this(User32.WM_USER)<br />
		{</p>
<p>		}</p>
<p>		public MessageWindow(uint msg)<br />
		{<br />
			_msg = msg;<br />
			CreateParams createParams = new CreateParams();<br />
			createParams.Parent = (IntPtr)User32.HWND_MESSAGE;<br />
			base.CreateHandle(createParams);<br />
		}</p>
<p>		public void Dispose()<br />
		{<br />
			base.DestroyHandle();<br />
		}</p>
<p>		public bool Post()<br />
		{<br />
			return User32.PostMessage(this.Handle, _msg, 0, 0);</p>
<p>		}</p>
<p>		private uint _msg;</p>
<p>		protected virtual void OnMessage() {}</p>
<p>		protected override void WndProc(ref Message msg)<br />
		{<br />
			if(msg.Msg == _msg)<br />
				OnMessage();</p>
<p>			if(msg.Msg == User32.WM_NCCREATE)<br />
				msg.Result = new IntPtr(-1);</p>
<p>		}</p>
<p>	}</p>
<p>}</p>
<p><strong>More Source Code;</strong><br />
using System;<br />
using System.Threading;<br />
using System.Reflection;<br />
using System.Windows.Forms;<br />
using System.Collections;</p>
<p>namespace Lab49.Utils<br />
{</p>
<p>	public class STADelegate<br />
	{<br />
		static STADelegate()<br />
		{<br />
			_dispatcher = new Dispatcher();<br />
		}</p>
<p>		public static Delegate CreateDelegate(Delegate dlgt)<br />
		{<br />
			DelegateProxy proxy = new DelegateProxy(dlgt, Thread.CurrentThread.ApartmentState == ApartmentState.STA);<br />
			Delegate contextdlgt = null;<br />
			try<br />
			{<br />
				contextdlgt = Delegate.CreateDelegate(dlgt.GetType(), proxy, &#8220;Invoke&#8221;);<br />
			}<br />
			catch(Exception ex)<br />
			{<br />
				System.Diagnostics.Debug.WriteLine(ex.ToString());<br />
			}<br />
			return contextdlgt;<br />
		}<br />
		static Dispatcher _dispatcher;<br />
	}</p>
<p>	public class DelegateProxy: ISTASafeDelegate<br />
	{<br />
		private Delegate _dlgt;<br />
		private static Dispatcher _dispatcher;<br />
		private object[] _args;<br />
		private bool _isSTA;</p>
<p>		static DelegateProxy()<br />
		{<br />
			_dispatcher = new Dispatcher();<br />
		}</p>
<p>		public DelegateProxy(Delegate dlgt, bool isSTA)<br />
		{<br />
			_dlgt = dlgt;<br />
			_isSTA = isSTA;<br />
		}</p>
<p>		public void ContextInvoke()<br />
		{<br />
		//	System.Diagnostics.Debug.WriteLine(&#8221;DelegateProxy Invoked from Dispatcher: &#8221; + AsyncDiagnostics.ThreadInfo);<br />
			_dlgt.DynamicInvoke(_args);</p>
<p>		}</p>
<p>		private void Invoke(params object[] args)<br />
		{<br />
			if(!_isSTA)<br />
				ContextInvoke();<br />
			_args = args;<br />
			_dispatcher.Dispatch(this);<br />
		}<br />
		private void Invoke(object sender, object[] args)<br />
		{<br />
			if(!_isSTA)<br />
				ContextInvoke();<br />
			_args = new Object[]{ sender, args };<br />
			_dispatcher.Dispatch(this);<br />
		}<br />
		private void Invoke(object retVal)<br />
		{<br />
			if(!_isSTA)<br />
				ContextInvoke();<br />
			_args = new Object[]{ retVal };<br />
			_dispatcher.Dispatch(this);<br />
		}</p>
<p>		private void Invoke(object sender, EventArgs e)<br />
		{<br />
			if(!_isSTA)<br />
				ContextInvoke();<br />
			_args = new object[]{sender, e };<br />
			_dispatcher.Dispatch(this);<br />
		}<br />
	}</p>
<p>	public interface ISTASafeDelegate<br />
	{<br />
		void ContextInvoke();<br />
	}</p>
<p>	/// <summary><br />
	/// Summary description for Dispatcher.<br />
	/// </summary><br />
	public class Dispatcher: MessageWindow<br />
	{<br />
		public Dispatcher()<br />
		{</p>
<p>			_operations = new Queue();</p>
<p>		}</p>
<p>		public void Dispatch(ISTASafeDelegate dlgt)<br />
		{<br />
			lock(_operations.SyncRoot)<br />
			{<br />
				_operations.Enqueue(dlgt);<br />
			}<br />
		//	System.Diagnostics.Debug.WriteLine(&#8221;Dispatching operation to GUI Thread: &#8221; + AsyncDiagnostics.ThreadInfo);<br />
			this.Post();<br />
		}</p>
<p>		protected override void OnMessage()<br />
		{<br />
		//	System.Diagnostics.Debug.WriteLine(&#8221;Message Rec&#8217;d: &#8221; + AsyncDiagnostics.ThreadInfo);<br />
			ISTASafeDelegate dlgt = (ISTASafeDelegate) _operations.Dequeue();<br />
			dlgt.ContextInvoke();<br />
		}</p>
<p>		private Queue _operations;</p>
<p>	}</p>
<p>}</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lab49.com/archives/87/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Firefox helpful hint of the day</title>
		<link>http://blog.lab49.com/archives/25</link>
		<comments>http://blog.lab49.com/archives/25#comments</comments>
		<pubDate>Wed, 13 Apr 2005 17:28:30 +0000</pubDate>
		<dc:creator>Mike Davey</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://daniel.lab49.com/wordpress/?p=25</guid>
		<description><![CDATA[This addin gives you more control over tabbed browsing. (eg new window links open in new tab)
Update:TabMix is now located here.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://hemiolapei.free.fr/divers/tabmix/tabmix.html.en">This addin</a> gives you more control over tabbed browsing. (eg new window links open in new tab)</p>
<p><ins datetime="2005-08-25T01:19:47+00:00">Update:</ins>TabMix is now located <a href="http://tabmix-en.blogspot.com/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lab49.com/archives/25/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MacroVision 2005</title>
		<link>http://blog.lab49.com/archives/7</link>
		<comments>http://blog.lab49.com/archives/7#comments</comments>
		<pubDate>Mon, 07 Feb 2005 14:35:27 +0000</pubDate>
		<dc:creator>Mike Davey</dc:creator>
				<category><![CDATA[Finance]]></category>

		<guid isPermaLink="false">http://daniel.lab49.com/wordpress/?p=7</guid>
		<description><![CDATA[Along the lines of Dan&#8217;s post, I thought that this was a pretty interesting research document from Morgan Stanley that came out last week.
In a nutshell, the main conclusions were as follows: 
First, this year&#8217;s MacroVision consensus believed there is no bond bubble &#8212; at least not in the traditional sense we might think of [...]]]></description>
			<content:encoded><![CDATA[<p>Along the lines of <a href="http://blog.lab49.com/?p=6">Dan&#8217;s post</a>, I thought that this was a pretty <a href="http://www.morganstanley.com/GEFdata/digests/20050124-mon.html">interesting research document</a> from Morgan Stanley that came out last week.</p>
<blockquote><p>In a nutshell, the main conclusions were as follows: </p>
<p>First, this year&#8217;s MacroVision consensus believed there is no bond bubble &#8212; at least not in the traditional sense we might think of one.</p>
<p>That&#8217;s especially true of government bonds, which were thought to be underpinned by generally well-behaved inflation, relatively well-positioned central banks, and a demographically inspired bid from pension funds noted below.   Riskier assets &#8212; especially high-yield, emerging market, and even investment-grade corporate paper &#8212; were perceived as being more vulnerable.  But any subsequent widening of spreads was not feared to be as market-disruptive an event as was the case in 1994 and again in 1998.  The group felt that this would be the first Fed tightening cycle where someone didn&#8217;t go through that proverbial windshield.<br />
<span id="more-7"></span><br />
Second, there was little doubt as to who would take the baton in a post-US centric world &#8212; it would be another encore for America.   There was deep conviction that no one comes close to having such an ideal system &#8212; especially in terms of technology, the work force, and America&#8217;s unique risk-taking culture.  Market depth and flexibility &#8212; in both the financial and the nonfinancial realms &#8212; was depicted as the icing on the cake for yet another run of US-centric global growth.  Eric Chaney and I made the case for productivity convergence between the US and Europe &#8212; as America eased off on IT-enabled capital deepening just when Europe was finally getting religion on this count.  A few eyebrows were raised, but there was far more skepticism than conversion.  The group felt any shifts in global leadership would occur at a snail&#8217;s pace.  Memories had apparently dimmed over how quickly the pendulum had swung away from Japan to Germany in the late 1980s.</p>
<p>Third, the demographic threat was generally not viewed as a serious problem for economies or financial markets over the next few years.</p>
<p>With the debate heating up on global pension reform and US social security privatization, we thought the time was finally right to grapple with this weighty issue.   The group didn&#8217;t bite.  They argued that this should be viewed not as a demographic problem but as more of a regulatory and political challenge that had important implications for the social policies of immigration and retirement ages.  The MacroVision consensus did concede that the asset-liability mismatch has important implications for moves into long-duration fixed-income assets, but concluded that any such shifts were likely to be glacial.  As one investor put it, &#8220;The demographic clock has plenty of ticks until the alarm goes off.&#8221;</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.lab49.com/archives/7/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
