LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

I don't want to use a "Stop" button....

I'm working on what will eventually become a stand-alone executable application and would like it not to have a "STOP" button to terminate the loops that are running.  I want the user to be able to click on the Windows's "X" (close) button to close the application, however, I want there to be some code that is run before the application closes.  For instance, I want the "X" event to stop some loops that are running, save some files (maybe with some user prompts), and clean up any open DAQ and VISA ports that may be open.

What is the most graceful way of doing this?  There are a few user events that handle this, such as "Application Instance Close", "Application Instance Close?", "Front Panel Close", "Front Panel Close?".......

-nickerbocker
0 Kudos
Message 1 of 18
(3,947 Views)
Take a look at the this link I think that it might help you.

Cheers!
0 Kudos
Message 2 of 18
(3,936 Views)
And give a look at the shipping example called Event Conditional Stop.
0 Kudos
Message 3 of 18
(3,931 Views)
If you're using an event case structure, I find that the "This VI" --> "Panel Close" case works well in your main VI. It doesn't fire when it's part of a sub VI, however, so be careful about that if you use sub VI containers on your front panel. I'm not sure whether "Application Instance Close" would fire, though I'm guessing "no," but keep in mind that my experience is limited to events in the main VI.

Here's an examle. The HV sub VI contains a "Panel Close" event with the same functionality as the Panel Close event in this picture, but the HV's event is tested as not firing when this main VI closes.

0 Kudos
Message 4 of 18
(3,925 Views)
Ok.  Right now what I have is in the right direction, but is not working the way I want it to be working.  I'm coming across a race condition with my shared network variables that is messing things up.  My code spans A lot of VIs across a rather large project so I'll do my best tod describe my problem and provide as much background as I can.

My Panel Close? event in my main program first initiates a "Shutdown" by setting a shared network variable named "Shutdown" to TRUE.  The stop condition in my polling loops and wired to this network variable "Shutdown."  Each one of those needs to execute their shutdown code and then send a signal to the Panel Close? code that they are done shutting down.  The Panel Close? code then polls a loop about twice a second and wait until everything has safely shutdown before closing the window that the user wants to close.

To acomplish this "Wait to shutdown" goal, I've created 1 network variable that is an array of clusters and 4 SubVIs:
  • Array of Wait to Shutdown Cluster
    • Wait to Shutdown Cluster contains, 1 boolean (safe to shutdown?) and 1 string (name or identifier for what we are waiting on).
  • SubVI - Add to Wait to Shutdown
    • Receives a string that is an identifier for that loop, outputs an integer that is a Wait to Shutdown reference number.
    • Add to the network variable "Array of Wait to Shutdown Cluster" an element with the received string and a false on the "safe to shutdown" item.
  • SubVI - Mark as Safe to Shutdown
    • Receives a Wait to Shutdown reference number.
    • Marks the "safe to shutdown" item true.
  • SubVI - Wait for Shutdown
    • Opens a window that has a list of each loop that we are waiting to shutdown and an indicator as to its status of shutting down.
    • Continuously loops until all the "safe to shutdown" booleans within the network shared variable "Array of Wait to Shutdown Cluster" are true or the user clicks on a button that says "Force Shutdown." 
  • SubVI - Clear Wait for Shutdown
    • Clears all the elements in the network shared variable "Array of Wait to Shutdown Cluster".

Now I'm not sure if a shared network variable is the most appropriate thing to use to accomplish my goals.  But I'm familiar with them and there is a potential that code running on a remote machine may need to get the same shutdown signals.  In fact, I'm almost certain that this will be the case.

The problem I'm running into is a race condition in my 'SubVI - Add to Wait to Shutdown'.  I have the problem of two instances of the SubVI - Add to Wait to Shutdown firing simultaneously, and one will overwrite the others entry but the outputs will have the same reference number :(.  I've set the SubVI up to be re-entrant, but I need a way of eliminating this race condition.

Also, any advice is welcome here.  Attached is an image of my 'SubVI - Add to Wait to Shutdown' code.

Thanks!
-Nickerbocker
0 Kudos
Message 5 of 18
(3,851 Views)
I'm no expert on problems of this nature, but you might want to read this while you wait for one, because that's where they keep sending me for questions about race conditions and variable types.
0 Kudos
Message 6 of 18
(3,815 Views)
Hmm..that was interesting and I'm going to try that approach.  The non reentrant section was interresting because my code did not work with the SubVIs either way :|.
0 Kudos
Message 7 of 18
(3,801 Views)
I don't now what is large for you, but I'd suggest you a lot of work on the architecture. Shared variables (or the older globals) are fast, easy, and lead to problems...
So here my guess, you've got several Vis running in parallel and communicating via shared variables. If that's the way you do it, make a search about producer/consumer design pattern. The basic idea is, that your main UI-Event handler steps out of the loop, starts to close all the communication (queues, notifiers), thus all the other loops will get errors (the codes ar 1122 and 1, you see that I really use that to now the codes by heart). As the error is present, each of the modules is starting the shutdown procedure (as they have to in case of any error), and afterwards I've got a SubVi which checks for error codes 1122 and 1 (note: if you use semaphores, the code for them is different) and clears these errors.

On good thing IMO is to have the error wire branch, feed the lower error in a clear error vi and then into the shutdown code, have the original error in the first input of a Merge error Vi (remove 1122 before) and the shutdown-error-wire to the second.

It's not easy (a lot of work) to implement it that way, but it makes your code pretty robust. During debug time, it's easy to find the module which dosen't terminate correctly.

Hope I was clear on that difficult topic, if not, I try to design an example....

Felix
0 Kudos
Message 8 of 18
(3,790 Views)
Following the advice given to me in this thread, this is the "Action Engine" I came up with.  Pretty simple and straight forward.  I call it a "Wait to Pass Action Engine."

Felix,

I understand what you are saying.  Unfortunetly, shared network variables are going to have to be a neccessary evil in some places in my design because I need to utilize the computer network infrastructure to transfer some signals across multiple programs.  But you have to admit, compared to other languages, globals in LabVIEW are a lot less error proned.

-Nic
0 Kudos
Message 9 of 18
(3,757 Views)
Woops..I was going to share my work....
0 Kudos
Message 10 of 18
(3,756 Views)