LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Start Asynchrounous Call if not already running

I have a non-reentrant VI that I'd like to launch asynchronously. I noticed that when I run "start asynchronous call" that it queues up a call to that VI. Is there a way to, instead of queuing the calls, to have the "Start Async" fail and return an error or something? I came up with this which sort of works but also has a small race condition in that if the launched program completes just after the the Wait on Asynchronous Call completes, the "Start Async" will not run because of the upstream error.

Launcher.png

Download All
0 Kudos
Message 1 of 15
(1,686 Views)

What about using a semaphore?

- 'Launcher.vi' would 'obtain a semaphore' reference of size=1 and pass it to 'Launched.vi'. 

- 'Launcher.vi' would try to 'acquire a semaphore' before calling 'Launched.vi'. If 'acquire a semaphore' times out don't call 'Launched.vi', if it don't times out call 'Launched.vi'.

- 'Launched.vi' would call 'Release Semaphore' when exiting.

- 'Launcher.vi' would 'Release Semaphore Reference' when exiting. 

 

Another option is to use a flag in 'Launcher.vi' used in similar way as the semaphore. 'Launched.vi' would have to signal its own exit to 'Launcher.vi', maybe via an user event to the calling event structure.

 

Hope this helps

UliB

0 Kudos
Message 2 of 15
(1,629 Views)

So, there's no mechanism to limit the call queue depth? It would be nice if NI provided example code of how they expect us to handle what has to be a somewhat common use case. What you've proposed is a pretty good idea but I see a couple corner cases that make it challenging.

If Launched gets aborted it never gets to clear its semaphore or fire off it's "I've ended event" and basically it gets stuck in a "not runnning" state

The method I provided actually solves this problem by using the existing non-reentrant semaphoring.

There's still a slight race condition where the semaphore is cleared or the event is sent but the VI keeps running and the call gets queued up.

 

0 Kudos
Message 3 of 15
(1,598 Views)

@nanocyte wrote:

I have a non-reentrant VI that I'd like to launch asynchronously. I noticed that when I run "start asynchronous call" that it queues up a call to that VI. Is there a way to, instead of queuing the calls, to have the "Start Async" fail and return an error or something? I came up with this which sort of works but also has a small race condition in that if the launched program completes just after the the Wait on Asynchronous Call completes, the "Start Async" will not run because of the upstream error.


Can you take a step back and explain the purpose of all this? Does the subVI ever return or is it running permanently?

If I have an asynchronous VI, I just place it on the toplevel diagram of the caller (outside any loops) and just use events to show the panel of the subVI if it is currently closed. Data communication is via an action engine.

(That's what I do e.g. for the "Spectrum display" window here. If we don't want to see it, we can just close its panel with the [X], but there is a button to show its windows again as needed)

Message 4 of 15
(1,586 Views)

@altenbach wrote:


Can you take a step back and explain the purpose of all this? Does the subVI ever return or is it running permanently?

If I have an asynchronous VI, I just place it on the toplevel diagram of the caller (outside any loops) and just use events to show the panel of the subVI if it is currently closed. Data communication is via an action engine.

(That's what I do e.g. for the "Spectrum display" window here. If we don't want to see it, we can just close its panel with the [X], but there is a button to show its windows again as needed)


The subVI does not return data to the top level but it does complete (it's not running forever)

 

I think your solution of having the VI always running is viable and I considered that design. I decided against it (perhaps prematurely) because Launched is rarely active and I would prefer it didn't use resources (threads, memory, etc) until it was launched and to minimize its resources when its front panel wasn't open.

0 Kudos
Message 5 of 15
(1,578 Views)

The race condition you mention is inescapable.

You want to check whether something is running, then decide what to action to take based on that, then perform that action.

But making the decision and starting the action will always take a finite amount of time; and during that time, there will always be the possibility the the VI that you checked, has completed.

Message 6 of 15
(1,555 Views)

 


@paul_a_cardinale wrote:

The race condition you mention is inescapable.

You want to check whether something is running, then decide what to action to take based on that, then perform that action.

But making the decision and starting the action will always take a finite amount of time; and during that time, there will always be the possibility the the VI that you checked, has completed.


I don't disagree. I was hoping there was a more elegant or standard approach.

0 Kudos
Message 7 of 15
(1,548 Views)

What you are doing is actually not common, which is why there isn't a standard way to do it.  And I suspect that "run if not currently running" is not the best way to solve your use case.  I don't know your use case, but as a general rule, interaction between async things is best done with messages, including "I have finished executing" messages, rather than tests to see if something is still running.

0 Kudos
Message 8 of 15
(1,529 Views)

This is not a standard approach.

So much so, I'm not exactly sure which behaviour you're looking for and why.

I'm pretty sure there is a better way to do this, but it requires understanding exactly what it is you're looking for (behaviourally)

0 Kudos
Message 9 of 15
(1,454 Views)

The example I provided has the behavior I want but it didn't look super easy to read so I was hoping for a better looking syntax. It's hard for me to understand exactly what's unclear. My use case also sounds similar to Altenbach's Spectrum Display window. But I'll do my best to try and describe a more specific example of where I might use this—

 

There are two VIs that each have their own jobs. The first one is running all the time and the second one (Launched) gets launched from the first one, does its thing and then should minimize its resources (cpu, memory, threads, etc). Most of the time Launched doesn't even get run at all. Imagine the Launched performs something like a calibration process where it wouldn't make sense to queue up multiple calibration procedures so I want to check if the calibration procedure vi is already running and notify the caller if it is. In the example I provided, this signal to the caller is accomplished with the error 123 from the timeout.

 

I assumed that most of the time, if the callee was not re-entrant, it would be common that the developer would want the non-stacking call behavior I described, and it sounds like some developers have already come up with their own work arounds (eg semaphores, always running subVI, and "I finished running" messaging) but it's possible I'm the weird one here.

0 Kudos
Message 10 of 15
(1,430 Views)