After looking at the QMH template built into LabVIEW 2015 I have some concerns over the execution order of the lower 'message handler' loop and the point at which the Register for Events is called on the Stop User Event.
It appears that the lower loop would technically be capable of firing the stop event before the register for events has actually been called meaning that this 'stop' event would not be captured by the underlying event engine.
I am aware that this is very pedantic point given the performance of multi-core processors but I feel that it might give users of the QMH the wrong impression of how to use more advanced event-based messaging.
My suggested fix would be to place both loops in a shared 'Error/No Error' case structure after the register on events has happened.
I would be interested in hearing other's opinions or if I am mistaken then I would appreciate being told where I am going wrong.
The ways that the QMH gets the Exit Message, I believe, are (a) because the User pushed the Exit button, (b) did a Panel Close?, or (c) generated an Error that was set to "Exit if Error" (generating a Message to the QMH).
The first two are processed by the Event Loop, so normal Data Flow requires the Register for Events to have been done. The Error situation requires processing by the QMH, including parsing at least two messages, Initialize and Exit, so only if NI's Round Robin parallel-loop time-slicing algorithm were really awful (or Register for Events took milliseconds instead of sub-microseconds) could this be an issue. Attempting to remediate it, I suspect, would lead to really "ugly" code and could well introduce yet other subtle bugs.
Still, it is probably a Good Thing to have spotted this "potential" for a Race Condition. If you are still concerned, put a 1 millisecond "Wait" between the Create User Event and Create All Message Queues.
My 2c would be to put the register for events directly after the function which outputs the event itself (before any actual events can be triggered). By introducing this data flow you are simply coding what is implied in the code, that any events triggered on that event will be registered for.
I don't think this leads to any bugs. Add "Clear Errors" if that's a cause for concern.
Thank you for your input.
I am inclined to agree with Intaris that wiring up the register events after the Create Stop User Event vi is a pretty straight forward solution which enforces correct dataflow without excessive uglification.
I guess NI might review it but as Bob Schor pointed out, it will always work so why would they change it?
I think drjdpowell has talked about race conditions with the QMH and with the (now fixed) DQMH, so it is perhaps a valid concern.
The problem would probably not be with the exit state, for the reasons Bob mentioned. But what if the developer calls the QMH externally followed by a new event "Init". You can argue that the "Init" code should be enqueued into the message loop when the QMH starts up, but it might have a parameter associated with it (e.g. VISA address for an instrument) so the developer thought it would be best to call the event from another VI and pass that parameter in. In this case, I think it is quite possible to generate the "Init" event before "Register for events" has occurred.
My solution would be to have the Event Initialization VI also output the registration.
Not only do I agree with Crossrulz (as is usually the case), it's "what I do". I have a VI that initializes the User Events, and outputs both the User Event Queue and the User Event Refnum. I wire the RefNum to the Event Loop Dynamic Event terminal, and wire the Event Queue to Generate User Event.
FWIW, we've adopted exactly the *opposite* habit as crossrulz and Bob_Schor, which is rarely the case. We explicitly modified the QMH template from LV 2013 to separate event creation and event registration since our normal usage pattern for these system-wide events was to need many distinct registrations for each of the many parallel threads.
We've finally started toward upgrading to LV 2016, where I see that the QMH template now does the same kind of separation. It no longer returns an event registration refnum from the code that creates the system-wide events. Either way can work if you keep your head straight, we just found the separation helpful as a reminder that *every* event handling loop would then be responsible for its own registration / deregistration.
I agree with the spirit of this suggestion. Even though I've never seen a bug attributed to this issue, it is still possible that it could occur. What do y'all think about me fixing it with this Merge Errors approach in LabVIEW 2017?