08-04-2023 04:06 PM
I use and highly recommend the JKI state machine as well. With that architecture, it's best to never have long-running loops in a particular state because they prevent the UI from receiving updates. Rather, you would call the same state repeatedly until the timer has elapsed, with an occasional check of the event structure to look for those important button presses.
08-04-2023 04:16 PM - edited 08-04-2023 04:17 PM
@aputman wrote:
I use and highly recommend the JKI state machine as well. With that architecture, it's best to never have long-running loops in a particular state because they prevent the UI from receiving updates. Rather, you would call the same state repeatedly until the timer has elapsed, with an occasional check of the event structure to look for those important button presses.
I will go a step further and say the OP should learn other architectures like the QMH or my favorite the CMH.
Think about this: In a Channeled Message Handler you can have several independent loops that can communicate with each other using Channel Wires. One loop can continuously monitor your UUT and tell the "Main Control Loop" to shutdown the test it the UUT exceeds a safe operating limit.
08-07-2023 08:39 AM
@RTSLVU wrote:
@aputman wrote:
I use and highly recommend the JKI state machine as well. With that architecture, it's best to never have long-running loops in a particular state because they prevent the UI from receiving updates. Rather, you would call the same state repeatedly until the timer has elapsed, with an occasional check of the event structure to look for those important button presses.
I will go a step further and say the OP should learn other architectures like the QMH or my favorite the CMH.
Think about this: In a Channeled Message Handler you can have several independent loops that can communicate with each other using Channel Wires. One loop can continuously monitor your UUT and tell the "Main Control Loop" to shutdown the test it the UUT exceeds a safe operating limit.
I have done something similar to that with the JKI SM. I didn't like the event structure being embedded within the SM....so I moved it into a separate loop. Now the UI is always responsive and I don't have to "poll" the event structure for user events to be processed during those longer running sequences.
08-07-2023 08:57 AM
@aputman wrote:
@RTSLVU wrote:
@aputman wrote:
I use and highly recommend the JKI state machine as well. With that architecture, it's best to never have long-running loops in a particular state because they prevent the UI from receiving updates. Rather, you would call the same state repeatedly until the timer has elapsed, with an occasional check of the event structure to look for those important button presses.
I will go a step further and say the OP should learn other architectures like the QMH or my favorite the CMH.
Think about this: In a Channeled Message Handler you can have several independent loops that can communicate with each other using Channel Wires. One loop can continuously monitor your UUT and tell the "Main Control Loop" to shutdown the test it the UUT exceeds a safe operating limit.
I have done something similar to that with the JKI SM. I didn't like the event structure being embedded within the SM....so I moved it into a separate loop. Now the UI is always responsive and I don't have to "poll" the event structure for user events to be processed during those longer running sequences.
Exactly! Honestly the State Machine is the most useful architecture and the first everyone should learn because most advanced architectures like QMH, CMH, Producer/Consumer, etc. have State Machines in each loop.
08-07-2023 11:25 AM
@aputman wrote:
I have done something similar to that with the JKI SM. I didn't like the event structure being embedded within the SM....so I moved it into a separate loop. Now the UI is always responsive and I don't have to "poll" the event structure for user events to be processed during those longer running sequences.
This is somewhat befuddling to me. The event structure is like a queue, events are stored until they can be processed; this is a lossless mechanism. Unless you have separate loops or use a call and forget for every case for handing different cases there can always be a lag between when you press a button and the response. Using a one separate loop to handle events and a second to process them, like the QHM, CHM, etc, doesn't necessarily increase responsiveness or reduce lag. It does increase program complexity and debugging. If the Event loop sends a message to a second loop and that loop is busy processing something else, how does that increase responsiveness? The JKI State Machine is set to go to the Idle state when it is not doing anything, no polling necessary.
For a long processing sequence you can introduce a quick go to Idle State to check if the user did anything. For example batch processing files:
08-07-2023 11:56 AM - edited 08-07-2023 12:01 PM
@mcduff wrote:
@aputman wrote:
I have done something similar to that with the JKI SM. I didn't like the event structure being embedded within the SM....so I moved it into a separate loop. Now the UI is always responsive and I don't have to "poll" the event structure for user events to be processed during those longer running sequences.This is somewhat befuddling to me. The event structure is like a queue, events are stored until they can be processed; this is a lossless mechanism. Unless you have separate loops or use a call and forget for every case for handing different cases there can always be a lag between when you press a button and the response. Using a one separate loop to handle events and a second to process them, like the QHM, CHM, etc, doesn't necessarily increase responsiveness or reduce lag. It does increase program complexity and debugging. If the Event loop sends a message to a second loop and that loop is busy processing something else, how does that increase responsiveness? The JKI State Machine is set to go to the Idle state when it is not doing anything, no polling necessary.
For a long processing sequence you can introduce a quick go to Idle State to check if the user did anything. For example batch processing files:
- Set Timeout to 1 // Change infinite timeout(-1) to 1 ms
- Process one file
- Go to Idle State // if there is an event react to it
- Decide whether to continue processing files, if true go to Step 2, if false set Timeout to -1
In my programs the GUI loop can directly "talk to" the other loops as necessary.
My "Instrument control loop" is basically sitting and waiting for a command most of the time, so it responds instantly.
My "main control loop" is written so in the "run state" it is just checking timers and checking for an incoming message from the GUI or safe operating limit loops. So it is also very responsive to the GUI.
On initial start up the main control loop is too busy to respond quickly. But this is before a test is in progress and during this time period I disable the front panels controls.
08-07-2023 12:03 PM
The state machine processes the UI events. They are added to the top of the state queue, which means they are processed at the next iteration of the SM. For my application, I disable buttons that can't be used during a test sequence.
When I say "polling", I mean exactly what you said in your step-by-step sequence:
For a long processing sequence you can introduce a quick go to Idle State to check if the user did anything.
I didn't like doing that, so I pulled the event structure out.
08-07-2023 12:33 PM
@RTSLVU wrote:
In my programs the GUI loop can directly "talk to" the other loops as necessary.
So you are using multiple(greater than 2) loops to increase responsiveness which I suggested earlier as one way to increase responsiveness.
08-07-2023 01:10 PM
@aputman wrote:
The state machine processes the UI events. They are added to the top of the state queue, which means they are processed at the next iteration of the SM. For my application, I disable buttons that can't be used during a test sequence.
So you have a state to check for UI events? I feel more inclined to really examine Norm's TLB', which allows for receiving commands as part of the SM loop, but not in the case structure. Again, I have not dived into the architecture, but that high level description (once I got it straight from the source) makes me want to look at it again.
08-07-2023 02:00 PM
@crossrulz wrote:
@aputman wrote:
The state machine processes the UI events. They are added to the top of the state queue, which means they are processed at the next iteration of the SM. For my application, I disable buttons that can't be used during a test sequence.
So you have a state to check for UI events? I feel more inclined to really examine Norm's TLB', which allows for receiving commands as part of the SM loop, but not in the case structure. Again, I have not dived into the architecture, but that high level description (once I got it straight from the source) makes me want to look at it again.
At one time, that was my intention to have a state that processed UI events and in that event, I could essentially prioritize them to be processed now or later. (link). Since that post, I have done away with that thought and now I just process UI events directly. Clicking a button executes a state in the SM....and I handle the prioritization thru the disabling of controls. I have found with software users (particularly ones that speak very little English) that if it looks like a button, it will be pressed.
I'll have a look at the TLB. That looks interesting.