04-19-2018 12:40 PM
I am coming directly from Queued Message Handler world and trying to adapt to Channel Wires. I feel like I'm trying to utilize Channel Wires too much like a queue where I can push/pop to the top/bottom of the queue to handle priority messages. Can someone give me insight into how this is or should be handled?
Example:
1) In Idle State with user making configurations in GUI
2) User presses the start button.
3) Information for running test is gathered and added to the messenger channel with a start message.
4) Messenger Starts testing (and continues testing by writing "continue" to it's own message queue)
Now if the user hits "Start Logging", or "Stop" does this get placed at the back of the queue or the front?? Will I have to wait for all of the "continue" commands to be handled before it sees the "Stop" command?
04-19-2018 10:20 PM - edited 04-19-2018 10:27 PM
I cannot give you a direct link right now, but you can find lots of discussion about these questions in the forum. I can add some links later when I find some.
Many developers are against using priority messages in a way that you add a msg to the front of the queue. There are certain arguments about why this design can cause problems. Instead, as i recall, you could use a separate queue/Channel to have a dedicated priority msg "line"...
edit: actually you read one of these posts already: https://forums.ni.com/t5/LabVIEW-Channel-Wires/A-new-channel-template-in-LV-2017-Event-Messenger/gpm...
04-20-2018 03:38 AM
Sending "continue" messages to oneself as a way to do repetitive actions is also something that many developers would consider a poor design.
04-20-2018 09:58 AM
I'm just looking to improve my code in any way possible, I don't claim what I have done is any good at all.
This method has been working for me and I'm ready to take the next step.
If I'm looking for the ability to have a continuously running data collection that I can start/stop with events, what is considered "good design" to accomplish that?
Thanks for any help you can provide drjdpowell
04-23-2018 03:28 PM
Actually, the "continue" message isn't bad, if one keeps it simple. But that confuses me as to what your question is, as a simple use just throws one "continue" message on the back of the queue, thus one never needs priority to get in front of "all of the "continue" commands".
Other techniques to get a continuous process in a loop are:
1) a "ticker" loop to send periodic "continue" messages
2) a "delayed message" (eg. 'send me "continue" in 100 ms')
3) a calculated timeout (where one calculate the time remaining to the next scheduled action, rather than use a fixed timeout). In the timeout case, do the "continue" action.
These techniques have the advantage of more precise timing, and you can have multiple periodic actions in one loop (eg. collect data every 200 ms, save to file every 3 seconds, check for and delete old files once a day).
04-23-2018 04:15 PM
Essentially this is what it does...
User hits "Start":
While data is being collected user hits "Log":
User hits "Stop":
04-23-2018 04:23 PM
Can you point to NI examples of these architectures?
Thanks!
04-23-2018 04:56 PM
@rkmadse wrote:
Essentially this is what it does...
User hits "Start":
- Loops starts to continuously perform data collection by logging a simple "continue" message to the queue each loop.
While data is being collected user hits "Log":
- "Log" is added as a priority and changes a state enum to a logging state so that when continue messages are executed, the logging code is performed rather than the run code.
User hits "Stop":
- Stop is added as priority message so that all of the queued "continue" messages are not performed.
Seems a bit strange to me. Why would the logging code and run code be mutually exclusive? Couldn't you just have the main loop (or even the producer loop) send the data, via a "logging" queue to a third loop which does nothing but log data, as long as the value of the log button is true?
04-23-2018 05:07 PM
Sorry I'm explaining things poorly.
State "Idle"
State "Run"
State "Run & Logging"
Hope that clarifies. The purpose of the priority messages is simply to change that state (enum with shift register) so that if the user wants to log he can log, if not then it just updates GUI. And when the use wants to stop everything, he can just simply stop it immediately and flush the queue of all other continue messages.
04-23-2018 10:42 PM
@rkmadse wrote:
Sorry I'm explaining things poorly.
State "Idle"
- Does nothing
State "Run"
- Collects data, and queues it for GUI updating.
State "Run & Logging"
- Collects data, and queues it for GUI updating.
- Also queues data to the Logging queue for logging.
Hope that clarifies. The purpose of the priority messages is simply to change that state (enum with shift register) so that if the user wants to log he can log, if not then it just updates GUI. And when the use wants to stop everything, he can just simply stop it immediately and flush the queue of all other continue messages.
I do not see why you need priority Enqueue-ing and Queue flushing in such case. Your data acquisition states (Run or the Run&Log) should not take long execution time, I always try to keep it below 1sec. So either doing a full state machine stop or changing states between pure Acquiring and Logging will happen in max 1 sec. As for design, i often use a simple Stream Channel with timeout I can change in the state machine loop. When I start acquisition, I set the timeout of the Channel read node to be zero, and using a local enum (or string based states which i prefer), I perform actions as needed (acquiring, logging, etc). Whenever a new Channel msg arrives, the timeout is ignored, and this very msg is processed first.
Benefits of this design is that you do not need priority insertion and queue flushing!