Excel RTD Servers: How to use UpdateNotify Properly
UpdateNotify is the primary method provided by the IRTDUpdateEvent callback interface that an RTD server uses to let Excel know that updates are available. I have however noticed that this method tends to be used incorrectly by many developers (specifically those developers without a strong foundation in COM). I’ve also received a few emails from readers reinforcing my belief that its proper usage is not obvious to many developers.
There are two very important requirements that you must keep in mind. This applies equally to developers using C# or C++ for their implementations.
The first is that the IRTDUpdateEvent interface pointer that the RTD server receives must only be called from the apartment in which it was received. Since this interface pointer is received in a call to the RTD server’s ServerStart method it follows that this interface must only be called from the apartment that the RTD server lives in. This is where a strong foundation in COM is helpful. If you’re a .NET developer you’re probably scratching your head wondering what on earth an apartment is.
I’ll leave a discussion of apartments for another day but at a minimum you need to understand that all COM objects (such as an RTD server) are grouped into apartments. A COM object lives in exactly one apartment and methods of that object can only be called directly from within that apartment. There are two types of apartments. The single-threaded apartment consists by definition of a single thread so only code on that thread can make direct calls to objects living in that apartment. The multithreaded apartment consists of one or more threads and objects living in that apartment can be called directly from any thread that belongs to that apartment. There’s so much more to say about apartments but that should be sufficient for this discussion.
A C# RTD server running in the same process as Excel will be created in a single threaded apartment. Therefore calls to UpdateNotify must only be made from this same thread that the RTD server lives on. How do you know which thread this is? It’s the thread that calls your object’s constructor and all of the IRtdServer methods. How do you ensure that calls to UpdateNotify are only made from this thread outside of one of the IRtdServer methods? One way is to send a message to a hidden window that is also living on that thread. The message pump provided by the single threaded apartment will dispatch the message to a handler on the thread and that handler can call UpdateNotify. This is why both of the minimal C# and C++ implementations use a hidden window.
For completeness I should mention (for the sake of nitpickers) that you may receive (or construct) an interface pointer that actually refers to a proxy object that allows you to call methods on the object from a different apartment. Developers with a background in COM may lean toward this approach. This is however not as useful as it sounds since it can lead you to call UpdateNotify excessively from a worker thread.
And this leads to the second thing to keep in mind. Excel will not update RTD functions more frequently than every two seconds or so. Therefore you should not call UpdateNotify more frequently than that. Some developers assume that Excel will faithfully respond to each call to UpdateNotify with a corresponding call to RefreshData. This is not the case. Remember also that since UpdateNotify is handled by Excel’s UI thread that excessive calls may lead Excel to become unresponsive since its message pump may be overwhelmed.
If you’re looking for one of my previous articles here is a complete list of them for you to browse through.
Produce the highest quality screenshots with the least amount of effort! Use Window Clippings.