LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Event structure intermittent/unpredictable

Solved!
Go to solution

I was finally able to extract my head from... well, you know.  All I really needed was an Asynch Call & Forget - start it up and let it run.  All these little guys do is listen for UDP packets, check & parse them, and send the resulting data to other processes.  The little twist was that, as Kevin suggests, I needed some way to stop it, so I made it into a queue-driven state machine, so that I could communicate with it via its Q when it needed to stop.  I never could figure out how to do all this within the same VI, so I had to create a separate VI that would 1) create the VI ref, and 2) create the Q refnum for me to use later.  Of course (obvious with hindsight) I couldn't do it all in the same VI because as soon as I wired an output for the Q refnum, it would have blocked execution and turned into "Call & Get Stuck".

 

This seems to be working, although I haven't tested it with more than 2 controllers and their corresponding UDP listeners.  I say 'seems' because I couldn't find any documentation or forum posts detailing how to do Asynch Call & Forget with reentrant clones. All I have for VI ref creation is the 0x08 flag.  I need to do more testing (maybe tonight) to confirm that I really do have independent, reentrant clones running.

 

So I've pretty much set things up as Kevin suggests - once again the blind squirrel finds the nut!  Thanks for thinking about this for me, Kevin - paul

0 Kudos
Message 11 of 18
(191 Views)

FWIW, I've found the help to be unclear, and possibly incomplete or ambiguous when it comes to reentrant clones and Async Call and [Forget; Collect].

 

Consequently, I've just kept sticking with the older & clearer "Call By Reference" function.  Then I can generate multiple independent clone instances by using only the 0x08 flag when opening the references.  (Of course the vi's themselves need to be set as reentrant too.)

 

The main purpose I see in the "Async Call & Collect" approach is to launch a time-consuming process whose output data is wanted, but without holding up other things while waiting for it.  But that's also the behavior one can get from a QMH construct once you're familiar with it.  So for me at least, there's no great advantage to worrying about the other flag options just so I can use 2 palette functions that separate start of execution from (one-time only!) data retrieval.

 

Basically, I've never even experimented much with "Start Async Call" or "Wait On Async Call" due to the reasons above.  I'm sure they're fine when used right, but it doesn't seem utterly clear to me how to use them right, and I already have other ways to get there from here.

 

 

-Kevin P

 

[edit:  P.S. bear in mind that *none* of the "Call By Reference" outputs are available until the called vi completes execution.  This includes the vi ref and error out that are built into the function.   So be mindful of dataflow!]

0 Kudos
Message 12 of 18
(186 Views)

I'm going to have to experiment with the Call By Ref to verify my (yes, superstitious) notion that it would be a blocking call, even if I wired no outputs from it.   For my app, I wanted to be sure that my calling process could set it up, start it and forget it, continuing to execute.

 

What I found interesting was what seemed to me to be an obvious omission from the Help - it tells us how to Call & Forget, it tells us how to Prepare for Reentrant Run, but it seems to imply that implementing both is unwise, impossible or generally tacky.  Under Call & Forget, it specifies "Do not use this option flag with 0x08...".

 

NI could, IMHO, double or triple the documentation on all this.

0 Kudos
Message 13 of 18
(180 Views)

Just to let folks know how I resolved all this:

 

1) I learned YET AGAIN that one cannot expect event structures to be able to handle events that were fired before their registration is finished - and that can take a little while - a random little while, which can cause unpredictable behavior.  I will henceforth heed the bruises on my forehead and use a 'handshake' to prevent sending events from starting to fire until the receiving event structure has finished registering.

 

2) Using the 0x08 flag with Asynch prepare to Call & Forget will work with separate, independent reentrant VI's.

0 Kudos
Message 14 of 18
(163 Views)
Solution
Accepted by topic author PaulOfElora

@PaulOfElora wrote:

Just to let folks know how I resolved all this:

 

1) I learned YET AGAIN that one cannot expect event structures to be able to handle events that were fired before their registration is finished - and that can take a little while - a random little while, which can cause unpredictable behavior.  I will henceforth heed the bruises on my forehead and use a 'handshake' to prevent sending events from starting to fire until the receiving event structure has finished registering.

 

2) Using the 0x08 flag with Asynch prepare to Call & Forget will work with separate, independent reentrant VI's.


The snippet at this link https://forums.ni.com/t5/LabVIEW/Ensure-Completion-of-Asynchronous-Loops-from-User-Event/m-p/3765409...

 

may help. It will tell you when the VI containing an Event Loop has started, but the actual Event loop may not be spun up yet.

 

mcduff

Message 15 of 18
(156 Views)

Whoa that's some deep magic there - much thanks McDuff!

0 Kudos
Message 16 of 18
(154 Views)

RETRACTION ALERT!!!   My comments about "Call By Reference" are generally wrong for launching an asynchronous vi.  Call By Reference behaves synchronously and won't return until the called vi stops execution.

 

I got myself mixed up due to some stuff I personally got used to doing way back when, more explanation below but feel free to skip.  The main point is, DON'T merely use "Call By Reference" to launch async vi's.

 

Background:  Back before the Async Call & [Collect | Forget] options were possible, I put together some auto-generating code that would give me Call & Forget behavior using the convenience of Call By Reference wired terminals.  

 

This auto-generated "launcher" vi would have the same terminal names and connector pattern as the core async vi I wanted to launch.  Inside the auto-generated launcher, I set up the core async vi with calls to the Set Control Value method followed by an actual async launch of it with the Run VI method.   The *effect* is pretty much what it sounds like Call & Forget can do.

 

So up at the app level, I've gotten used to the pattern of using "Call By Reference" on my launcher, and it returns pretty much immediately, while the underlying core code can continue to run asynchronously.

 

Sorry for creating confusion.

 

 

-Kevin P

0 Kudos
Message 17 of 18
(131 Views)

Thanks Kevin.  I should also add my $0.02 and reiterate my learning that one can indeed launch multiple reentrant clones using the Asynch call with the 0x80 Call & Forget option, yay!

0 Kudos
Message 18 of 18
(119 Views)