LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

simple case strucutre causes labview to hang

So to deal with Sir Altenbach's comments first. Yes, the extra while loop is a waste. it was a holder from the translation from a producer/consumer architecture. 2) My understanding of event structures is that they only "lock up" the front panel while they are executing a case. All of the code in the Idle event structure by design takes essentially no time to execute, so that isn't an issue. Turning off the lock option on all the cases did nothing.

 

As for the second event structure in the acquire case - that handles the data driven part. I tried to work that into the main event structure without success. Part of the issue is that you can't define the dynamic event until the task is defined and it goes away when the task is destroyed. If I want to use the channels for multiple tasks, i can't leave the task lying around. Again I would point out that the program works just fine executing that loop and never hangs.  When the code hangs it does so without ever reaching the part of the code with the data driven event structure so trying to blame the issue on code that never gets executed seems unlikely. If someone has a simple example of using a data driven architecture within a state machine I would be interested in seeing it. Subject to the requirement that the tasks don't exist for the whole duration of the program

 

I don't believe the "constructive" code constipation comment requires a reply.

 

Thank you Nathand for pointing out the co-erce issue. I believe the issue there is that I added cases to the enum after first using it and Labview somehow notices how many cases there should be. I have found that so long as you are careful to add new enums to the end of the list this doesn't cause problems. After all the enum gets translated into an integer and that is what gets fed into the state machine on the next pass. I used to cast my controlling enums as types but that caused issues when I tried to add a case since it redefined the type and I had to go back through the code doing a lot of replacements.

0 Kudos
Message 11 of 23
(1,742 Views)

@rossu wrote:

I don't believe the "constructive" code constipation comment requires a reply.


It is a technical term describing a case where there is not dataflow dues to deadlock and other issues. Do you have a better term?

0 Kudos
Message 12 of 23
(1,739 Views)

rossu wrote:

Thank you Nathand for pointing out the co-erce issue. I believe the issue there is that I added cases to the enum after first using it and Labview somehow notices how many cases there should be. I have found that so long as you are careful to add new enums to the end of the list this doesn't cause problems. After all the enum gets translated into an integer and that is what gets fed into the state machine on the next pass. I used to cast my controlling enums as types but that caused issues when I tried to add a case since it redefined the type and I had to go back through the code doing a lot of replacements.


Please don't take this the wrong way, but you're doing it all wrong. You don't "cast" your enums as a type. You define a type definition, and then EVERY use of that enumeration is an instance of that enumeration. Yes, the first time you do it, you'll have to do a lot of manual replacements. But after that, every time you want to add a new case, you edit it in only one location - the type definition- and every use of that type definition gets updated automatically. When you right-click and create a constant from a wire that's carrying a type definition, the constant is automatically linked back to that type definition, so there's not even any extra work involved (although you can, of course, also get an instance of the type by going to Select a VI... and finding your control).

 

I noticed that your enums have a "Report Err" case that's never used - which is good, because you also didn't define a case for it. So, which case executes if Report Err were to show up on the wire? The default case, which is "Start Acq". Is that what you want? Of course, because you didn't use a type definition, there's a huge risk in removing that unused case from all your enums - what if you miss one? Every case after that will have the wrong value. With a type definition, you wouldn't have this problem - you'd remove it once, and it would vanish everywhere.

Message 13 of 23
(1,727 Views)

@nathand wrote:

Learn to use Type Definitions! I'm not certain this is the problem, but it might be:

CoercionDot.png

See the little red triangle? That indicates that the data types don't match. The enums are not all identical. LabVIEW will use the numeric value, not the text value, to determine which case to go to next. Your Actions enumeration should be a type definition, and every Action constant should be linked back to that it, so that when you update the list of enumeration values in the type definition it is reflected everywhere that enumeration is used.


Right you are!  do a search for "Stop Acq" exclude hidden .... the only way to get to the Stop Acq" State is error in Start Acq.  The Acquire state has a "Stop Acq" enum coerced to "Idle"

 

Now that we looked closer at the Acquire state..... Were you planning on unregistering that dynamic event or, did you really want that huge memory leak and all those events pilling up without an event structure around to handle them?  (I didn't think so)

 

VI Analizer essentially made a sad face when it peeked in on that code

Capture.PNG


"Should be" isn't "Is" -Jay
Message 14 of 23
(1,722 Views)
I will look at that. It "should" be impossible to get to the timeout case in Acquire. It normally exits because either the stop button gets pressed or because cycles =cycle limit. In fact, I haven't looked at the stop button since turning this into a state machine earlier today and the logic might not be right. My issue is that I make offset something like -25 and error limit something like 5. Hitting Go (stop button=true) sends me to Pre Acq. If the daq read operation in pre Acq returns something like 0 (I.e. Someone forgot to turn on some hardware), it tries to run the False case. A warning message is sent and the system returns to idle. We never enter Start Acq or Acquire. However, when the program returns to idle it would appear that the ui events have been disconnected from the event handler I.e. It just goes round and round the timeout without responding to any of the events it should.
0 Kudos
Message 15 of 23
(1,702 Views)

Have you read my message number 4?

 

You still have multiple event structures buried in different cases with events set to lock the front panel.  If an event locks the front panel, and you need to do something else in order to get to the event structure that processes that event case, your stuck.  That will make it look like "the UI events have been disconnected from the event handler". 

 

A properly architected VI with only a single event structure that isn't stuck inside a case structure wouldn't have this problem.  It's not impossible to have multiple event structures, but unless you really, really know what you are doing, then you are going to mess them up.  And the "Lock front panel" setting is the key to "locking up" your UI when you don't really want to.

0 Kudos
Message 16 of 23
(1,694 Views)

The solution such as it is.

 

In the Acquire loop the Stop button change value event is wired into the event structure  This meant that the event was wired in in two event structures, the idle case and the Acquire case. Removing it from the acquire case and wiring the button itself into the circuit caused the problem to go away.

 

It is somewhat puzzling that this was an issue as the program would hang without the Acquire case ever being executed. If you think of it as event handlers in C code, then one might expect both stop value change cases to be affected but not any other case. However, it completely disconnected all of the events in the Idle case.

 

Moral of this story: DO NOT wire the same event into two event structures, even if it is impossible for them both to be active at the same time. It might be OK if they are dynamically connected in each case.

0 Kudos
Message 17 of 23
(1,649 Views)

RavensFan explained your problem. The events are not "disconnected." The problem is that in the event configuration, you have "Lock front panel until the event case for this event completes" set (this is the default). As the help explains, "By default, when an event enters a queue, LabVIEW locks the front panel that contains the object that generated that event. LabVIEW keeps the front panel locked until all Event structures finish handling the event. While the front panel is locked, LabVIEW does not process front panel activity but places those interactions in a buffer and handles them when the front panel is unlocked."

 

As with a C event handler (since you seem to like that comparison), once you register to handle the event (in LabVIEW, by creating an event structure and adding a case for the event), that event handler is active regardless of what part of the code is executing. The code for that event won't run until execution reaches that event structure, but the event itself is put in the queue so that it can be handled as soon as the event structure is reached. Combine that with the front panel locking, and you have the behavior you saw: the event gets put in the queue, causing the front panel to lock, and then there's never any way for execution to reach the event structure that handles the event so the front panel never gets unlocked.

Message 18 of 23
(1,638 Views)

Event structures are active and queuing up events all the time, whether they are in the current path of execution, a future path of execution, or even a path that will never be executed.  If you have those events set to lock front panel until the event is complete, then you can completely lock yourself out from ever executing the code again.

 

Be sure to read Caveats and Recommendations when Using Events in LabVIEW - LabVIEW 2014 Help what you just discovered is part of the things listed in that document.

Message 19 of 23
(1,635 Views)

@RavensFan wrote:

 

 

A properly architected VI with only a single event structure that isn't stuck inside a case structure wouldn't have this problem.  It's not impossible to have multiple event structures, but unless you really, really know what you are doing, then you are going to mess them up.  


That is an excellent candidate for LabVIEW Proverbs!


"Should be" isn't "Is" -Jay
Message 20 of 23
(1,601 Views)