LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

What is the preferred way to stop multiple loops?

When developing large programs consisting of multiple parallel loops, often in different subVIs, I have used many different mechanisms to stop the loops when ending the program. (Queues, notifications, global variables, references etc). I find that they all have pros and cons and I’m therefore wondering if there is a preferred way.
Message 1 of 51
(7,573 Views)
I almost exclusively use the error output of a Queue or Notifier. Release the Queue or Notifier in the main loop when all is done, and all the others shut down, in the order you want them to.
Richard






Message 2 of 51
(7,557 Views)

Having reread your post, I see you are looking for "the" preferred method. I'm not sure there is one. You're likely to just get opinions, like the one I posted, which was basically useless without explaining why I like doing it that way.

 

One of the most common uses you see for a local in example programs is to stop a loop. However, you can't use a latching type Stop button with a local (reason 1 to not use a local). So you'll have to use yet another local to turn "off" the Stop button on the way into the program (reason 2 to not use a local). Reason 3 to not use a local is that it makes an necessary data copy. Reason 4 is that the diagram is harder to read (somewhat of an opinion). Globals have all these caveats and more.

 

I feel a little better having explained myself.

Message Edited by Broken Arrow on 12-07-2009 03:22 PM
Richard






Message 3 of 51
(7,543 Views)
I don’t think there is a correct answer to this question either, but I would like to get peoples opinion on this question. I have a bad habit of using a global variable or functional global (due to simplicity), but I know this is not a preferred way.
0 Kudos
Message 4 of 51
(7,531 Views)

I usually use queues but in a somewhat different manner.  I prefer to send a command, such as "Halt," to the other loops via the queues.  This is one value in a type-def'ed enum.  The lower level loops send back a status value of "stopped," usually another enum. It requires pairs of queues between loops.

 

This allows an arbitrary level of coordination or sequencing of the shutdown process.  I also find the concept of shutting down on an error to be unintuitive and at odds with comprehensive error handling.  If you do shut down on the queue error, that should be documented.

 

Lynn 

Message 5 of 51
(7,527 Views)

I do the same as Broken Arrow.  All of my programs have a Queue.  In loops that consume from the queue, I stop them on error.  If I'm worried that the Queue might error, i stop them on the specific error of the queue dissapearing.  For loops that don't use the queue, and just wire in the "Queue Status" vi and check the "error out" signal in the exact same way.

 

I dislike the "STOP" button because it doesn't fit into the standards for User Interfaces on any system.  I don't see a "STOP" button in my web browser or word processor, for instance.  So the problem with breaking the stop button because of creating a local variable isn't ever a problem for me.

 

For me, I use the "Panal Close" or the "Panal Close?" events to release my program queues and to perform any clean-up code.  If I'm in the development stage of my application, I make a menu command (generally Execute->Stop VI) that serves as my "STOP" button so that I don't have to close the window to execute my shutdown code.

Message 6 of 51
(7,517 Views)

johnsold wrote:

I usually use queues but in a somewhat different manner.  I prefer to send a command, such as "Halt," to the other loops via the queues.  This is one value in a type-def'ed enum.  The lower level loops send back a status value of "stopped," usually another enum. It requires pairs of queues between loops.

 

This allows an arbitrary level of coordination or sequencing of the shutdown process.  I also find the concept of shutting down on an error to be unintuitive and at odds with comprehensive error handling.  If you do shut down on the queue error, that should be documented.

 

Lynn 


 

What is the purpose of the type-def'ed enum?  I'm not sure I understand why you would want a simple U16 value type-def'ed.  I don't see the bennefit in doing that.  Maybe if the properties (like the strings[] one) of the enum automatically updated to controls and constants that reference the type-def.  But this is not the case.  I wish it were the case, because it would make working with Enum's a lot simpler. 

 

I understand your problem with using the error out to stop a loop as being unintuitive, but you can use the technique w/o it being at odds with comprehensive error handling.

Message Edited by Nickerbocker on 12-07-2009 04:59 PM
0 Kudos
Message 7 of 51
(7,502 Views)

What is the purpose of the type-def'ed enum?  I'm not sure I understand why you would want a simple U16 value type-def'ed.  I don't see the bennefit in doing that.  Maybe if the properties (like the strings[] one) of the enum automatically updated to controls and constants that reference the type-def.  

 

Message Edited by Nickerbocker on 12-07-2009 04:59 PM

Whoa!

 

Create a Strict Type def of an enum.

Add an item to it

Select File: Apply changes:

 

All controls, indicators and CONSTANTS in memory are updated!

 

Any that are not in memory will * when you open them (since they refer to the type def) and saving updates them as well.

 

A Type def'd enum is pretty darn powerful


"Should be" isn't "Is" -Jay
Message 8 of 51
(7,483 Views)

You don't even necessarily have to make it a strict typedef.  A regular typedef will auto-update all controls, indicators, and clusters when you make changes to it and hit "apply changes".  I agree with Jeff, a typedef'd enum is very powerful.  A cluster containing one of those, and a variant for passing any type of data, is a terrific way to communicate between states in a state machine, parallel loops, subVIs, etc.

 

Myself, though, if I'm just causing everything to stop with the press of a button, I like to use a notifier, which I invariably name "stop".  (creative, aren't I?)  Then I just obtain that notifier for use in my subVIs, and pass the reference along to any loops I have running in my main VI as well.  It's worked well for me.

 

That being said, a pair of queues (as Lynn uses) would also work well...I can see instances where it would probably work better.  And for the record, I'm also not a fan of using an error wire to stop loops.  Certainly you can trap for the specific error and perform a controlled shutdown based on it, but I think there are better ways to do things.

Message 9 of 51
(7,487 Views)

My preferred method depends on the type of loop I am stopping.  Here are the major options:

  1. Event loop - Use a user generated event on a simple boolean to generate a STOP event. I use this commonly to close multiple windows or "invisible" servers (e.g. string server or error server) on application exit.
  2. Queue-based task handler - Use a STOP task.  You can also force kill the queue and treat an error like a stop, but this overloads the error condition, resulting in more complex programming.  I prefer to send a STOP task and use the cleanup to kill the queue.
  3. Polled loop - use a "safe" global (e.g. action engine, single-element queue, or data value reference, NOT a global) to signal a shutdown.  Check at each iteration of the loop and OR its condition into any other local stop conditions.
There are other variants (e.g. notifier-based task handler will be like a queue-based task handler), but this covers the main use cases.  In all cases, make sure you have a cleanup phase to close references and put any hardware into a safe state.
Message 10 of 51
(7,432 Views)