12-19-2014 03:20 AM
Hi guys,
So I am thinking about a software architecture of a short project that I have. (actually thinking about converting a recently started code
)
I had some thoughts about creating a Message Handler Loop with a statemachine inside.
Instead of creating different states as strings, I created two different sequences as messages called "sequence1" and "sequence2" (attached screenshots)
Any ideas on how this could be bad or good?
12-19-2014 07:01 AM
This sounds more like a Queued State Machine to me (a state machine that uses a queue to maintain what states to run). I use QSMs all the time and they work very well, as long as you are careful about what states you call.
12-19-2014 11:33 AM
Right, the idea is pretty much queued state machine. The implementation is different.
Well, atleast the queued state machine I know would queue up different messages as states
and would execute them in the order that is queued.
The implementation I suggested would stay in that case(or just queue up same message over and over)
until that specific sequence is finished or some other message has been called to execute.
I was just wondering if the implementation would be beneficial at all to convert some parts of it to a single case and stay in that case.
12-19-2014 11:54 AM
@doradorachan wrote:
I was just wondering if the implementation would be beneficial at all to convert some parts of it to a single case and stay in that case.
In general, it is a bad idea for a state machine to stay in a single state for any length of time. At the very least, you should be checking for UI or other types of messages. But having a state enqueue itself so that it is ran again is something I do all the time. I normally enque a check for UI events and then itself again if that is what is happening.
12-19-2014 11:58 AM
Right. That is what I am also trying to do when i "stay" in that single case.
If you look at "screenshot.png", you can see that I am putting the same message "sequence 1" into queue
until that sequence is finished. This gives a chance for UI and other messages to executed while that sequence 1 is executing
12-19-2014 12:12 PM
The only time I have ran into an issue with that setup is if you receive an Abort command. You have to make sure you clear out your state queue and then return to the Idle state. But that could potentially clear out important commands (like stop the program) if you just letting any loop enqueue states on you. That is why I prefer to have the state machine itself handle the queue.
12-20-2014 04:54 PM
Dear Dora,
In some ways, a Queued Message Handler is a State Machine, with the "states" being the Messages. It's not clear to me why you have Sequence 1 and Sequence 2 as "Messages", rather than Action 1, Action 2, etc. When you encounter Action 1, you "do the Action", and then decide what to do next. If it is always the same thing, simply call "Action 2" (or whatever), otherwise have a Case statement that decides the next Action. You might well be able to simplify the data passed on the Shift Register, as Action 1 and Action 3 (I presume these correspond to Sequence 1 and Sequence 2) would not be needed.
Bob Schor
12-21-2014 11:42 PM
Hi Bob_Schor,
The reason I put Sequence 1 and Sequence 2 as messages is because I thought
then I could create typedef data cluster that will hold information for each sequence independently.
For example, lets say I had sequences called, "Measure New Stuff" and "Measure Returned Stuff" and actions called "Measure" and "Log".
Both sequences will call "Measure" and "Log" eventually, but there will also be some other process involved that are different for each sequence.
So I thought if I created Sequence 1 and Sequence 2 as messages, then I could handle the results of "Measure" and "Log" in a similar fashion for both sequences, but still differently.
Currently I just put "Measure" and "Log" into a subVI so the reuseable portions will be the same for both sequences. (attached screenshots)
I used to just lay out actions as messages and call them in the required order just like you are suggesting.
But then I noticed the state information was harder to keep track of due to the reason I just mentioned previously.
12-22-2014 01:41 PM
I don't know how you are creating your screen shots, but they are not helpful -- they are larger than my monitor, and also do not show the entire block diagram (they are cut off on the left and on the bottom). Do you know how to make Snippets? If you have a Snippet, you can Insert Image (the tenth button on the Forum's Toolbar), it will put your code (yes, the Snippet can be opened as code) right in the message, and we can see what's going on.
Here's an idea. As I understand it, Sequence 1 and Sequence 2 both do more-or-less the same thing, but with (perhaps) some slight differences. Use a Boolean or an Enum to register whether you're doing Sequence 1 or Sequence 2, but don't make them separate Messages, just keep them on a Shift register in your Message Handler. Suppose Sequence 1 was "Action A, Action B, Action C", while Sequence 2 was "Action A, Action D, Action C". Furthermore, suppose you want to do "Sequence 1, Sequence 2". Proceed as follows:
Yes, the logic is a little more complex, but not that bad, and you only have a single State Machine/Message Handler to worry about. See if this works for you.
Bob Schor
12-27-2014 03:55 PM
Sorry, not sure why I didn't think of the snippet. But you totally got the idea.
I guess I thought just showing the case structure of the message handler would save space and would be easier to look.
I used to use the method you described.
But the more sequence I implemented, I noticed that organization was becoming a problem.(managing sequence specific data and such)
That's why I thought about creating different sequence as a message so that it would be more manageable.