07-16-2010 05:11 AM
Hi,
I am trying to get more familiar with some LV architectures. So I have tried to use an asynchronous producer-consumer architecture with a queued state machine to handle a very simple GUI (rather than considering a do-while loop polling for events).
Here is my example GUI :
3 booleans : Open, Tools and Exit
and one command which is a graph
And the actions are the following :
Open: display a new graph
Tools: display graph tools
Exit : stop everything
The user shouldn't be allowed to use Tools if there is no graph displayed. On the other hand, he should be able to exit the program at anytime or or generate a new graph at anytime. Which is why I call these different actions GUI level 1 (open and exit) and GUI level 2 (tools). Through this forum and the multiple examples i have read, it seemed that an event driven queued state machine was the best suited for this. But It's still unclear for me given the fact that the state is queued on the producer loop, dequeued in the consumer one and linked to a condition structure that will execute the corresponding code. And I am not checking at anytime which state I am in...
I finally do it in the event structure before queuing another state!
PS: I know that I could disable the Tools button until Open was pushed but I would rather avoid that solution.
I have also thought of using different queues for the different "levels" of actions (in case of a more complex GUI).
Thanks for your comments and your suggestions!
Chris
07-16-2010 05:26 AM
As further references, read this blog post on expressionflow
Also you might having a look at this advanced concept in my community nugget on event based messaging
As a comment on your code, I think that you should try to make a better error handling. You can just generate errors at diffrent sections of the code (producer loop, consumer loop, before the obtain queue) and see how your code hangs (or works).
Felix
07-19-2010 02:43 AM
Thank you very much for these very interesting articles. I really learned a lot with them (I was doing a QSM-PC without knowing it!). But they partially answered my question (I am not sure that I was clear though...)
How can I handle events that must happen at different levels of the User Interface?
Open, Exit = all the time
Process = only if Open was clicked before (message error if not).
It looks very simple but I am still stuck with it... The precedent .jpg shows how I handled this but I am not sure that's an elegant or suitable solution
THanks
Chris
07-19-2010 04:06 AM
Ok folks!
I found on another thread that what I am looking for is a Hierarchical State Machine and such an architecture can be found on lashsm.com. I haven't looked at it deeper than the description offered by the website but it looks very efficient for event-driven interfaces.
Chris
07-19-2010 07:30 AM
I can't get to lashsm.com. Was it misspelled?
07-19-2010 07:31 AM
It's LabHSM.com.
07-19-2010 08:57 AM
Chris,
What you are seeing is one reason that I have avoided the QSM. I prefer to send (via a queue of course) a command from the GUI producer to the consumer( which implements a state machine). The command is evaluated according to the current state: So, if Command = "Process" and State is not one which is reached after the Open command, then disregard the command and send a Status message to the user which says "Process is not a valid command until after Open." If the state is one for which Process is valid, then execute the Process command.
Lynn
07-19-2010 10:12 AM
On a style note, you also have an opportunity via the GUI design to control the choices the user can make. When I write code that others will use I have a goal for the GUI, do not present the user with a choice that he/she can't make. You can control this through visibility or enabled properties depending on taste. In your case, the process button should not be enabled unless open has been pressed.
As you have noticed, the code can get pretty hairy if you have to respond to all of the crazy choices those wacky users are bound to make. Restricting those choices can help keep it manageable, not simple, but at least tractable.
Just my 1.5 cents.
07-22-2010 09:19 AM - edited 07-22-2010 09:21 AM
@Darin.K wrote:
the code can get pretty hairy if you have to respond to all of the crazy choices those wacky users are bound to make.
Which was the very first error I made when I started to code and tried to respond to all possible choices...
@johnsold wrote:
I send a command from the GUI producer to the consumer( which implements a state machine). The command is evaluated according to the current state
Sorry but I don't get the difference between what you do and and the QSM. Tell me if I am wrong : The command you send is a new state that you just compare to the current one and you do it in the consumer loop rather than in the producer loop.
If so, It's something very similar to what I did, the difference is that I did it in the producer loop and I don't register the event if it doesn't correspond to a valid state.
But I think I missed something...
Thanks all for your help
Chris
07-22-2010 09:36 AM
Chris,
I do not send a "State." The command is interpreted within the state machine to determine if a change of state is appropriate.
For example if the Save command is sent but no data has been acquired or the file does not exist, then the state machine does not go the the Write to File state, but to an error state or a Get File state.
In other words the Producer can ask the state machine to do something but it cannot tell it what state to execute next. The state machine processes the queue output as an input which helps determine the next state, not as the state itself. The producer in general does not know what state the state machine is in and, therefore, cannot know whether a particular state is appropriate as the next state. This may be a matter of philosophy more than computer science, but that is the way I see a state machine. The QSM architecture can work fine, but is it really a state machine?
Lynn