LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Wait on Asynchronous Call - why so long?

Solved!
Go to solution

LV 2013, Win7

 

I have a window which comes and goes, during program operation.

 

This window has 72 subPanels, each containing a reentrant copy of the same VI for a "block".  I insert the VI in the subpanel, and then run the VI with a CALL and FORGET call.

 

When the user closes the window, all the block VIs terminate, and the window closes.  I don't care if the closing behind the scenes still goes on after the window disappears.

 

But when the user QUITs the program, with this window up, I need to make sure that all the block VIs have terminated before I shut down other things (close files, etc).

 

To that end, I changed the CALL and FORGET to a CALL and COLLECT operation, and installed a WAIT ON ASYNCHRONOUS CALL for each instance at the end of the big window code.  This is after the blocks have been commanded to die (via an event).

 

I see from the debugging file (a portion is pictured) that it takes over 1000 mSec to wait for all the instances to die.

 

 

Wait at Quit.PNG

 

 

The thing is, if I change that "0" to "1000", then what I would expect is that the actual waiting time would drop to < 100 mSec.

My thinking is that during that timed wait, the blocks would be dying anyway, so it would take less time to actually wait on them.

 

But when I do that, nothing really changes.  The listed time is still over 1000 mSec.

 

If I limit the number of blocks to 12, the time is 97 mSec, for 24 it is 185, for 36 it is 576, and so on - it's proportional to the number of blocks.

So, what is really happening?  If it's just waiting on things to die, why doesn't the timed wait affect the numbers?

 

I originally  (when I used CALL and FORGET) kept track of how many were opened and how many were closed and waited until that became zero, but this is a cleaner way of doing it, at least in theory.

 

Am I missing something?

Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 1 of 36
(3,743 Views)

Have you checked how long the first loop of the For loop takes, versus all of the others?

 

I wonder about the order in which your subVIs close, versus the order in which you wait to collect them. Let's say that you send the stop messages in the reverse order from how you're waiting to collect them. If the last one to stop is the first one you're waiting to collect, that first loop cycle will take a very long time. After that it should go more quickly, but assuming there's some fixed amount of time required for each collect, it will increase proportional to the number of instances.

 

Also, I'd expect that it will take 72 VIs a while to each receive and process the "Die" event. Is that still occurring while you're waiting to collect?

0 Kudos
Message 2 of 36
(3,727 Views)

I wonder about the order in which your subVIs close, versus the order in which you wait to collect them. 

 

 

--- I thought about that.  It's an EVENT that stops them. Each block has an EVENT loop and they all receive the same event.

I can't (nor do I want to) control the order in which they quit.

 

So yes, the first loop will wait on block #0 to quit, but that could be last to actually quit.

 

But that would be OK - if #0 is the last to quit, then I would expect the other 71 blocks to just breeze right thru.  If all it's doing is waiting until it's dead, then it's faster if they're dead already, right?

 

 

 

 

Also, I'd expect that it will take 72 VIs a while to each receive and process the "Die" event. Is that still occurring while you're waiting to collect?

 

I send the STOP event, close the big container window FP, and then wait to collect.  I tried waiting before closing the panel, to no good effect - it just keeps the window up while I collect.

 

 

 

Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 3 of 36
(3,719 Views)

Just to make sure, because you only show parts of the diagram:

 

When does the "wait" start executing? While it does not have any data dependency (and thus can start immediately) the loop depends on the references, so we can't really tell how long it takes until they arrive and the case structure is allowed to execute.

 

Can you add a few more timestamps, e.g before and after the for loop? For comparison, what results would you get if you would put the wait inside the case structure instead?

0 Kudos
Message 4 of 36
(3,714 Views)

Hmmmm.  It's a bad plan to CONDITIONALLY do the COLLECT operation.

 

The help text says "Every Call node with 0x100 option (call & collect), must have a corresponding Wait on Asynch node, or the reference is not freed."

 

If I bail out and restart the whole computer, and remove that CONDITION, so that it collects every time, then the time is 390 mSec, not 1000.

Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 5 of 36
(3,707 Views)
Solution
Accepted by topic author CoastalMaineBird

You might consider another approach to ensuring that all of the subpanel instances have exited, such as a queue. Each instance puts an element in the queue when it finishes, then exits. Your cleanup code dequeues elements in a For loop that runs once for each instance, so after every instance has exited it can proceed. This way you don't care about the ORDER in which the subpanels exit, you just confirm that they all finished. Should be lower overhead than call&collect.

0 Kudos
Message 6 of 36
(3,701 Views)

Have you checked how long the first loop of the For loop takes, versus all of the others?

 

 

So I tried that, several times - the pattern is the same as shown here.  The first few lines are from the blocks themselves, it's the last thing they do.

 

Looks like there's ONE case where there's a bigger delay than expected,  All told, this takes about 600 mSec.

 

Maybe the debugging process affects that (* waves to Mr. Heisenberg * )

 

 

The 300-400 mSec is back to where I first saw this delay.  Apparently the unreleased refs clog up the system enough to drive it up to 1000 (or 2000 mSec as I saw in one case).

 

Still, I don't understand why a timed delay ahead of the WAITS doesn't affect the WAIT time.

 

But I guess that's not important.  It must be actually doing more work than simply asking "is it dead yet?"

 

 

 

 

 

Call and Collect.PNG

Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 7 of 36
(3,699 Views)

When does the "wait" start executing? While it does not have any data dependency (and thus can start immediately) the loop depends on the references, so we can't really tell how long it takes until they arrive and the case structure is allowed to execute.

 

 

--- A reasonable question.  In frame 4 (of a sequence), there is an event loop.

Code outside this big window issues a STOP event.

This event is registered by the container window, and by each of the 72 blocks.  They all see it.

The container window, reacts by stopping the WHILE loop in frame 4

In frame 5, it stores a single integer into a PREFS (.ini) file and closes the front panel.

In frame 6 is the COLLECT code you see above.

 

Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 8 of 36
(3,693 Views)

You might consider another approach to ensuring that all of the subpanel instances have exited, such as a queue. Each instance puts an element in the queue when it finishes, then exits. Your cleanup code dequeues elements in a For loop that runs once for each instance, so after every instance has exited it can proceed. This way you don't care about the ORDER in which the subpanels exit, you just confirm that they all finished. Should be lower overhead than call&collect.

 

--- That's a good idea.  That's actually similar to what I started with (today), which was a "manager" (functional global) type VI.  Each instance called this, and it incremented a count.  when it quit, it called it again and decremented the count.

 

I sat there looping until the count went to zero.

 

I was thinking this was a bit more elegant than the "are we done yet?   are we done yet?" approach, but it looks like the overhead is significant.  I don't need to "collect" anything, but the process takes at least 5 mSec each.

Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 9 of 36
(3,689 Views)

OK, I took your idea and changed it a bit.

 

In the container window, I create a queue, and I pass that queue to each of the 72 blocks.

Each block puts one item INTO the queue when it STARTS, and the last thing it does is take one item OUT.

 

So, when the container wants to wait for everybody, it simply looks for an empty queue.  The time is about 320-360 mSec.

And it doesn't have to know how many to expect.

 

If I DO add the timed wait before checking, it DOES subtract from the overall time, as I would expect.

 

Thanks, nathand !

 

Stop Queue.PNG

Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 10 of 36
(3,664 Views)