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)
BeginInvoke(new EventHandler(OnDataChanged), new object[] { sender, e });
else
{
……
}
}
Maybe it’s just me, but having to say “Please do whatever you need to do before you do what I’m about to tell you to do” 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.
The key to this solution is the Windows User32 function PostMessage, which will allow you to put a message into the application’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?
Message-Only Windows
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.
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.
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.
The first step is to define an interface that our Dispatcher will use to invoke the the underlying delegate. Let’s call it STAInvoke (for Single Threaded Apartment, the threading model employed by windows forms that made all this necessary in the first place.) Read more...