LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 
Reply

How to handle hanging processes in QSM

Last Plug for JKI State Machine. (I do not work for them)

 

  1. When installed via VIPM additional tools are installed. One tool allows you to right click on a string in a constant or in a case structure and "Find Callers" (see image below) This would allow you to find orphaned states or misspelled states, although going through hundreds of states this can be tedious. But it is useful for debugging.
  2. They are open source. I made some suggestions to their code and they incorporated and improved them.

mcduff

 

Snap52.png

0 Kudos
Message 11 of 21
(166 Views)

 

 


@mcduff wrote:

Last Plug for JKI State Machine. (I do not work for them)

 

  1. ..., although going through hundreds of states this can be tedious. But it is useful for debugging.
  2. ...

 

 

Head_Explodes.gif

 

Please see here.

 

Spoiler

 

After a dozen or so states, it may be good time to learn how to create sub-VIs. They don't hurt really! If we document them well they actually make the code easier to follow. 

Smiley Wink


 

 

 

Ben

 

0 Kudos
Message 12 of 21
(162 Views)

@Ben wrote:

 

 


@mcduff wrote:

Last Plug for JKI State Machine. (I do not work for them)

 

  1. ..., although going through hundreds of states this can be tedious. But it is useful for debugging.
  2. ...

 

 

Head_Explodes.gif

 

Please see here.

 

Spoiler

 

After a dozen or so states, it may be good time to learn how to create sub-VIs. They don't hurt really! If we document them well they actually make the code easier to follow. 

Smiley Wink


Ben

 


Each state has it own subVI (like below), it that wrong?

 

Snap53.png

 

I like to make subVIs that do only one small thing (atomic like states), it then becomes easier to refactor code later, and rearrange "macros".

 

For example an Initialize State may have an IDN*? command, a Clear Command, and an Open Reference Command.

Rather than make one subVI called Initialize that contains all three of those states, I prefer to make 3 States and an Initialization Macro. This allows me to reuse the Clear, Open, *IDN?, later in my program without the other states.

 

Is this bad practice?

 

 

mcduff

0 Kudos
Message 13 of 21
(155 Views)

Somewhere the history of LV A Finite State Machine los the word "Finite". "Finite" as in limited number of transitions. While simple application built using a QSM can be controlled and drawn up as a State Transition Diagram, they can grow out of control and before you know it chaos.

 

The diagram below is one of my busier state machines and was developed back before the Event Structure was trusted (by me) using what is called the State Diagram Editor. I offer as an example how a Finite State Machine can be documented. There are some QSMs that defy documenting the state transitions.

 

State_Diagram.JPG

 

Bad practice?

 

I will let others deal with absolutes like that.

 

What I can say is that I have found it extremely useful to include a State Transition Diagram in the block diagram of my code to allow others to be able to understand my or even better remind ME Whiskey Tango Foxtrot did I do?

 

Someone here has a signature that read "code like the person that follows you is a psychopath and knows where you like."

 

I code by the hour and on occasion my code has undergone audits by NI and others. The embedded state diagrams go a long way toward helping others understand my code.

 

"

For example an Initialize State may have an IDN*? command, a Clear Command, and an Open Reference Command.

Rather than make one subVI called Initialize that contains all three of those states, I prefer to make 3 States and an Initialization Macro. This allows me to reuse the Clear, Open, *IDN?, later in my program without the other states.

"

 

Instead a Macro have you considered a sub-VI called Initialize that invokes the three sub-VIs?

 

and just for the record...

 

Yes I have worked with the QSMs when my customers where comfortable with them and could not get their heads around not using them. The trivial QSM were OK but when it came time to do anything complicated (like handling Timeouts from more than one instrument) it often became a challenge trying to figure what was happening in what order.

 

With ah Finite State Machine the transitions are well defined. With a QSM, the transition order may never be the same from run to run. And then if we start throwing "enqueue at the front"... God help us!

 

Just my two cents worth,

 

Ben

 

Message 14 of 21
(149 Views)
Highlighted

I feel that nobody so far has really answered the question of how to do a "fail-safe" timeout.  When writing your own LabVIEW code you can usually find a way to write it with a timeout that always works.  But if your code has to call code other people write, either in DLLs, library code you can't change, or code written by other devs merged in later, then you can't be certain any of it will work.

 

Here's a possibility:

 

Timeout via call and collect.PNG

 

If you use a call-and-collect asynchronous call, you can run arbitrary LabVIEW code from within that VI. Then, if it doesn't return within an anticipated time frame, you can either:

1. Wait longer by calling a "collect" again later, but do other code in the meantime

2. Close the reference to the VI, which stops its execution.

 

The "Collect" node's timeout isn't dynamically settable as you can only set it during edit time, but you can set it to a rather short time and then call the node in a loop N number of times to effectively have a dynamic timeout as long as it's a multiple of the timeout you set during edit time.  

 

This can be a bit dangerous though as not closing the VI reference can lead to having a memory leak, but closing it can stop execution in an unexpected place which might cause other issues.

Message 15 of 21
(141 Views)

@Kyle97330 wrote:

Nice method. Never knew that right-click menu existed for the timeout.

 

mcduff

0 Kudos
Message 16 of 21
(133 Views)

Ok Ben,  I'm finally going to attempt a challenge on your dislike of Ouroboros.   And,  I will use hermetic symbology to develop my caseSee link

 

Classically,  Ouroboros is a symbol of completeness or ALL.  The entirety of an existence with purpose.   Just like an application! a means to bring about all thing desired by that designer by enforcing rules upon some Silicon dioxide impregnated with a few well placed impurities. 

 

In Hermeticism the ALL spawns guides and controls aeons, Angel's and, elementals to enact it's purposes.  Collectively,  these may be  Event loop driven QSMs each spawned for a purpose.

 

The event loops represent the Aeons controlling the duration of the purpose.guided by the ALL.  The reciever tha commands of the application (Events) such as launch, begin, pause, abort,etc... and interoperate these events according to the requirements of the predefined purpose.

 

The Angels are, of course, the messages to the elementals that accomplish tasks needed to fulfill the purpose for the Aeon's existence. These messages may have priority!  A higher calling of the ALL, may demand that the purpose must " Abort, retry, fail"  because the existance of the Event driven QMH is under AUTHORITY  of the Application. 

 

The Elementals are then the States.  These exist to perform tasks needed to aid the purpose.  They may be File Elementals (open/Create, write, read, Close...)  IO Elementals,  Analyze Elementals,  you get the idea but, each task knows what it is supposed to do and, importantly,  if it succeeds!  The state result does impact the Angel's! Either by enquiring another state or even destroying the queue or notifying the ALL an error occured some message transpired from each state.

 

Now we speak of the easy way to wrap yourself into a problem.  The worst thing that can happen is you create one Aeon to achieve all purposes!  Don't Do That!

 

If the purpose is simple, the ALL may be the GUI and only one Event driven QMH is needed for the application.  If there are several purposes you need multiple QMHs.  (One reason I do not encourage the JKI State Machine is that it just begs to abuse this division of purpose  if you have a "Macro" you need another Aeon)

 

Ouroboros is good!

0 Kudos
Message 17 of 21
(128 Views)

@Jeff·Þ·Bohrer
@Ben

I understand Ben's point. I tend to make large macros which may/do obfuscate purpose. I do it for two reasons, one it keeps my program as lightweight as possible (do not have subVI duplication in states), two it lets me reuse code in different ways. Here is an example that @Jeff will not like.

I allow my user to make their own DAQ tasks, they are all dynamic and not programmed in MAX. A while back there was an issue with closing and opening tasks, so I tried to reuse tasks as much as possible.

So if a user just updated the gain of a channel and nothing else, then I could reuse the task. So in my macro ConfigureDAQ I have an argument that lets me know if a task can be reused, and my macro is only slightly different when I new task is needed. Unclear, yes/maybe, but seemed easier at the time, then making two subVIs with mostly redundant block diagrams.

 

@jeff still digesting what you posted. Nice to see you more often on the boards.

 

mcduff

0 Kudos
Message 18 of 21
(124 Views)

@mcduff wrote:

@Jeff·Þ·Bohrer
@Ben

I understand Ben's point. I tend to make large macros which may/do obfuscate purpose. I do it for two reasons, one it keeps my program as lightweight as possible (do not have subVI duplication in states), two it lets me reuse code in different ways. Here is an example that @Jeff will not like.

I allow my user to make their own DAQ tasks, they are all dynamic and not programmed in MAX. A while back there was an issue with closing and opening tasks, so I tried to reuse tasks as much as possible.

So if a user just updated the gain of a channel and nothing else, then I could reuse the task. So in my macro ConfigureDAQ I have an argument that lets me know if a task can be reused, and my macro is only slightly different when I new task is needed. Unclear, yes/maybe, but seemed easier at the time, then making two subVIs with mostly redundant block diagrams.

 

@jeff still digesting what you posted. Nice to see you more often on the boards.

 

mcduff


I haven't been hiding... just lurking. 

 

Ben does have valid points and good reasons to fear uncontrolled state transitions.   Frankly, I think he has transferred a distaste for a snake that bites itself in random locations (biting off it's own tail or other needed parts) with a complete modular design that eats itself only at the tail and controls application execution.   Giving a misconception of Ouroboros as a wild, crazed beast that grows uncontrollably. 

0 Kudos
Message 19 of 21
(106 Views)

@Jeff·Þ·Bohrer wrote:

...

 

Ben does have valid points and good reasons to fear uncontrolled state transitions.   ...

 

with a complete modular design that eats itself only at the tail and controls application execution.  ...

 

a wild, crazed beast that grows uncontrollably. 


If you read what I had intended to say, you will see that was my point about the QSM. Like a worm eating its tail, it is best kept small and only being fed a small amount lest it should devour itself.

 

The Queue in a QSM is most easily controlled by only feed it one thing at a time. When we start throwing pile so meat on it plate is where things get messy.

 

G-Story Time!

 

About 20 years ago, the LabVIEW advanced course was not being taught by NI since they had not purchased it from Viewpoint Systems. In that course they touched on architectures that included "Action Engines" and the QSM. That was about as advanced as it got back then.

 

The QSM filled a gap that was needed to bring more people into the world of LV from more traditional languages. Prior to LV developers thought in terms of a list of operations that need to be executed in a specific order as were comfortable with ideas like Goto, Push on the stack, pop-off the stack etc.

 

The QSM let developers that had that mindset stick with their traditional way of thinking but use a graphical method to express that mindset.

 

Now a customer of mine attended that class and went at it. Stated with  a small simple QSM and did his own coding. As time passed he kept building on the same single QSM and found that he could not maintain it anymore and hired my company to keep up with keeping the application growing. My rookies went at it and fixed some of the issues of "doing everything in one loop" by launching background processes to move some of the other tasks out of the main QSM.

 

The customer liked what the rookies had done and got back into doing the code himself. It was not more than a year latter that the code came back (once and for all!) to us. What we found is the customer took the idea of background thread to the extreme and was now firing of background process like crazy. But to make it worse he piled on the QSM pushing items into the queue (on to the stack) both at the front and the back.

 

Trouble shooting problems that would occur depending on the phase of the moon ( order of states in the queue) was a nightmare. I recall sitting with e developer and seeing 50 or more states in the queue. Often the issues were traced down to the order of execution getting hosed. I will repeat myself in saying the QSM invited chaos.

 

Done with the story for now.

 

That chaos is easily prevented in LabVIEW using Finite State Machines, data flow paradym, modular code that does specific functions well and interact s needed to integrate the components.

 

Instead of designing application that consist of an uber-QSM that know all and does all, assemble a set of specialist that do their assigned duties well and play nice together.

 

A small digression...

 

If we look at database design there is the concept of a "fully normalized" database where no piece of information is duplicated and keys are sued to establish the relationships between various data sets.

 

A similar idea can be used in LV design by establishing what data is associated with each of the functions in an application decide who needs to touch what data when and in what ways. Then assign that data to the appropriate components using the most appropriate synchronization methods. What you end up with a nice clean architecture where multiple developers can play in their own sand box and when it comes time to get the gears to mesh, that machine works smoothly and nobody looses any teeth I the process.

 

Enough for this morning's ramblings...

 

Ben

 

Message 20 of 21
(88 Views)