I just found the Application.Idle event (actually I just read a startup use of it in Kean's Through-the-Interface blog... Thanks Kean & Peter!). I needed to instantiate an object in the application context thread during startup and found that (outside of VS Debug) the IExtensionApplication.Initialize() does not run in the application context thread. After realizing there is this Idle event I thought I'd give it a try... lo and behold, it does run in the application context thread. I also played around with the Entering and LeavingQuiescentState events as well. Turns out they also run on a thread separate from the application context thread. So I have two questions:
- What's the internal difference between the Application.Idle event and the Entering/LeavingQuiescentState events? I should note that I have already learned that the Idle event is associated with the Application Context and is also raised continuously as long as the system is not "idle" and that the Entering/LeavingQuiescentState events are associated to the active documents which requires registration/deregistration of the events as documents change. So really what I'm asking is... what defines "idle" and what makes this different from the Entering/LeavingQuiescentState events?
- Being that the Application.Idle event is hit continuously, I have a couple of choices to manage my code. One is to place a boolean constraint so that the event code would only run once on startup, but this will mean some use of resources to process the event and constraint. The other would be to simple deregister the event after it enters the first time. Both have their pluses and minuses. If I use the boolean constraint approach (maybe to compare states periodically) can this create any major issues worth considering?
Solved! Go to Solution.
Applications have message queues where windows places input-related messages (mouse, keyboard, etc) that the application needs to process. The application runs in a loop called a 'message pump' which basically keeps checking the queue to see if there are any pending messages, and if there are, it processes each of them, until the queue is empty. At the point when the application returns from processing queued messages and checks the queue again, it is in the 'idle' state. Each time that happens, the idle event is raised.
Entering and leaving quiescent state are preciesely what their names imply. When AutoCAD is polling for input while there are no active commands (e.g., at the command prompt), it is in a 'quiescent' state. When it is busy doing something, it is in a 'non-quiescent' state. Entering/LeavingQuiescentState signal the transition between those two states.
As far as your problem, it's easy to solve. In your Initialize() you can add a handler to the Idle event. Event handlers can remove themselves from the event they handle when they are invoked. When your handler for the idle event fires, do whatever you need to do, and then have the handler remove itself from the idle event, so that it will never be called again. That allows you to handle the event once after adding the handler and without the need for a sentinel.
That's actually exactly what I did. I wanted to make sure I understood what was going on underneath as well because I didn't want to inadvertently create issues due to my lack of knowledge. I appreciate your reply, very informative. In fact, I didn't even know the Application.Idle being related to AutoCAD's messge queue. Where the quiescent state originally threw me off was the fact that the event is tied to the active document class. So (in understanding that AutoCAD uses fibers and is not a true multi-threaded environment) I wasn't sure if this meant it had a similar application, but from the document context.
Again thanks for the information and confirmation that I'm not too far off base.