Jump to content

References Opened in VIs called with "Run VI" method


Recommended Posts

Hello everyone.

I have an application where I call most VIs with the "Run VI" method (Wait until Done = T, Auto Dispose Ref = F). In some of these VIs I open references (DAQmx Tasks, IMAQdx sessions etc.) that should be kept open after the VI stops running, because I need to use them later in other VIs. I am using a functional global to store the references.

An example of this is starting a DAQ counter Task, storing the Task in a functional global. Later getting the Task from the functional global and read out the value of the counter.

The issue is that references opened inside a VI called with the "Run VI" method are closed by LabVIEW when the VI stops running, in an attempt to avoid memory leaks (at least that is what I think it is). How can I awoid this?

Hope you can help me out.

/Simon

Link to comment

Hello everyone.

I have an application where I call most VIs with the "Run VI" method (Wait until Done = T, Auto Dispose Ref = F). In some of these VIs I open references (DAQmx Tasks, IMAQdx sessions etc.) that should be kept open after the VI stops running, because I need to use them later in other VIs. I am using a functional global to store the references.

An example of this is starting a DAQ counter Task, storing the Task in a functional global. Later getting the Task from the functional global and read out the value of the counter.

The issue is that references opened inside a VI called with the "Run VI" method are closed by LabVIEW when the VI stops running, in an attempt to avoid memory leaks (at least that is what I think it is). How can I awoid this?

Hope you can help me out.

/Simon

Set autodispose ref to true and don't close the ref in the calling vi.

http://zone.ni.com/reference/en-XX/help/371361E-01/lvprop/vi_run_vi/

Link to comment

Shaun, the problem is not with the VI ref, but with other refs opened inside the dynamic VI.

The general rule for reference cleanup is that a reference is automatically destroyed when the top-level VI in the hierarchy where it was created stops running. In this case, the dynamic VI is the top level VI.

What you want to do for something like this is change the hierarchy which owns the reference. One way of doing this is to make sure the LV2 global is first loaded in a hierarchy which remains in memory (e.g. by having your main VI call it first). Another is to move the reference generation to a daemon which runs continuously and stays in memory. The daemon can accept requests using mechanisms like queues or user events.

Link to comment

What you want to do for something like this is change the hierarchy which owns the reference. One way of doing this is to make sure the LV2 global is first loaded in a hierarchy which remains in memory (e.g. by having your main VI call it first). Another is to move the reference generation to a daemon which runs continuously and stays in memory. The daemon can accept requests using mechanisms like queues or user events.

Why not just add a Create method (for the reference type you want to create) to the LV2 global, instead of the Add Reference (or whatever it may be called).

/J

Link to comment

Shaun, the problem is not with the VI ref, but with other refs opened inside the dynamic VI.

The general rule for reference cleanup is that a reference is automatically destroyed when the top-level VI in the hierarchy where it was created stops running. In this case, the dynamic VI is the top level VI.

What you want to do for something like this is change the hierarchy which owns the reference. One way of doing this is to make sure the LV2 global is first loaded in a hierarchy which remains in memory (e.g. by having your main VI call it first). Another is to move the reference generation to a daemon which runs continuously and stays in memory. The daemon can accept requests using mechanisms like queues or user events.

Thanks for you reply Yair

I do load the functional global (F.G.) into memory first, in my main VI (this actually is a set of costum steps used in TestStand so i load the F.G.'s in a initialization step). However, this is apparently not enough, since LabVIEW still closes the references even though they have been moved to the F.G.

I would really like not to have to open the references in a daemon, since it is quite advanced DAQ that is going on (up to 6 parallel tasks sharing triggers and sample clock across two cDAQ systems) with many different setups. Is there no way to protect a reference from labview cleanup?

Can I disable the cleanup for specific VIs or just turn it on and off when I dont want it to destroy my references?

Why not just add a Create method (for the reference type you want to create) to the LV2 global, instead of the Add Reference (or whatever it may be called).

/J

Thanks for your reply Mellroth

What you are saying is basicly the same as Yair, move the create reference to a daemon (or F.G. type external handler) which is in memory outside the VI called by the Run VI method. It will solve the problem, but the complexity of the application will also become much greater.

If there is no way to work around the LabVIEW cleanup I guess I will have to move the creation of references to an external handler.

I wish there was a way to tell LabVIEW not to run the cleanup or to protect specific references.

Edited by ssv
Link to comment

Shaun, the problem is not with the VI ref, but with other refs opened inside the dynamic VI.

The general rule for reference cleanup is that a reference is automatically destroyed when the top-level VI in the hierarchy where it was created stops running. In this case, the dynamic VI is the top level VI.

What you want to do for something like this is change the hierarchy which owns the reference. One way of doing this is to make sure the LV2 global is first loaded in a hierarchy which remains in memory (e.g. by having your main VI call it first). Another is to move the reference generation to a daemon which runs continuously and stays in memory. The daemon can accept requests using mechanisms like queues or user events.

Ahh. IC. Been a long weekend :P

I use self initialising vis for exactly this (usually, VISA and IMAQ). Not a million miles away from a functional global, but it keeps the reference local to the vi using it and is released when the vi is closed.

something like this....

Link to comment

Ahh. IC. Been a long weekend tongue.gif

I use self initialising vis for exactly this (usually, VISA and IMAQ). Not a million miles away from a functional global, but it keeps the reference local to the vi using it and is released when the vi is closed.

something like this....

Hi ShaunR

Yes using self initialising VIs for VISA and such is very effective. It is however not exactly what im looking for. The references I need are IMAQ sessions and DAQ Tasks, they cannot just be opened and closed like a VISA COM port.

Link to comment

Really?

So I can't do this then :)

No! Once the Top level VI, in whose hierarchy the Open/Create/Obtain LabVIEW refnum was executed, closes, that refnum is disposed without mercy. VISA is a notable exception since you can change in the LabVIEW options that VISA sessions should not be autodisposed.

Rolf Kalbermatter

Link to comment

Really?

So I can't do this then smile.gif

No you cant, if you later run a "Get" to get the image out via the reference then it will return an error since the image reference has been closed down. Remember that images are transferred "by reference", there is no image data in the wire. And I need to access the image in a later step.

Similarly with Tasks, if I start a task (for instance a counter) then I cant just restart it if it has been closed down - it is continously counting of pulses.

Link to comment

No! Once the Top level VI, in whose hierarchy the Open/Create/Obtain LabVIEW refnum was executed, closes, that refnum is disposed without mercy. VISA is a notable exception since you can change in the LabVIEW options that VISA sessions should not be autodisposed.

Rolf Kalbermatter

Not if you set autodispose to true when you load the vi dynaimically.. Then the launched vi is responsible for closing its own refnum so the IMAQ refs remain until you close the launched vi. Perhaps I should have started with the IMAQ example instead of the VISA. I only chose visa because it was the first pallet item I came accross (visa autidispose is the first thing I set when installing LV by the way).

No you cant, if you later run a "Get" to get the image out via the reference then it will return an error since the image reference has been closed down. Remember that images are transferred "by reference", there is no image data in the wire. And I need to access the image in a later step.

Similarly with Tasks, if I start a task (for instance a counter) then I cant just restart it if it has been closed down - it is continously counting of pulses.

As I pointed out, this technique keeps the ref local to the vi. If you want to access it outside the vi then you have to transfer it using a queue or global. If you need to do this then its not for you and the normal functional global is more appropriate.

Link to comment

Not if you set autodispose to true when you load the vi dynaimically.. Then the launched vi is responsible for closing its own refnum so the IMAQ refs remain until you close the launched vi. Perhaps I should have started with the IMAQ example instead of the VISA. I only chose visa because it was the first pallet item I came accross (visa autidispose is the first thing I set when installing LV by the way).

Well but that is about the VI refnum itself. However this does not solve the issue with other refnums opened inside that VI once that VI goes idle (even when the autodispose is set to ture when opening the VI ref and that VI does not close its refnum itself) and in TestStand this is the most simple way to open common resources, by opening them in a pre-sequence step. However that step simply runs and then stops.

The only way to circumvent that is to keep the VI you are launching in the pre-sequence step running as a deamon and then shut it down in the post-sequence step.

Rolf Kalbermatter

Link to comment

Well but that is about the VI refnum itself. However this does not solve the issue with other refnums opened inside that VI once that VI goes idle (even when the autodispose is set to ture when opening the VI ref and that VI does not close its refnum itself) and in TestStand this is the most simple way to open common resources, by opening them in a pre-sequence step. However that step simply runs and then stops.

The only way to circumvent that is to keep the VI you are launching in the pre-sequence step running as a deamon and then shut it down in the post-sequence step.

Rolf Kalbermatter

I think we are both arguing the same point :unsure:

As I said. The self configuring vi (and yes I can do the above in both DAQ and IMAQ as well as VISA) keeps the refs LOCAL to the vi. If it (the one that was launched) goes idle then yes the refs disappear and I wouldn't have it any other way. However, if the launching vi goes idle then the vi remains running unless the AutoDispose was set to false (as in the OPs case) in which case it no longer remains running and halts when the calling vi exists and bang goes your refs. If there were such a thing it would be a "Daemon" design pattern.

For the OPs case, this self configuring daemon seems a bit awkward since he has no way to access the refs because he can't call it as a sub vi. That can easily be overcome with a global (oooh dare I say it :) ) or simply reading the ref control with a property node. However the general intent is NOT to make the refs global but encapsulate complexity to make an autonomous, fire-and-forget sub system.

Link to comment

I think we are both arguing the same point :unsure:

We probably did :rolleyes:.

As I said. The self configuring vi (and yes I can do the above in both DAQ and IMAQ as well as VISA) keeps the refs LOCAL to the vi. If it (the one that was launched) goes idle then yes the refs disappear and I wouldn't have it any other way. However, if the launching vi goes idle then the vi remains running unless the AutoDispose was set to false (as in the OPs case) in which case it no longer remains running and halts when the calling vi exists and bang goes your refs. If there were such a thing it would be a "Daemon" design pattern.

For the OPs case, this self configuring daemon seems a bit awkward since he has no way to access the refs because he can't call it as a sub vi. That can easily be overcome with a global (oooh dare I say it :) ) or simply reading the ref control with a property node. However the general intent is NOT to make the refs global but encapsulate complexity to make an autonomous, fire-and-forget sub system.

Well there is another solution although it is in fact in a sense a global too. And your original solution with the IMAQ ref already goes a long way into that direction.

Make that VI an Action Engine or as I call them an intelligent Global with a method selector. Calling the Init method from the pre-sequence where it does the opening of the resources (and that deamon stays in memory polling the same or another Intelligent Global for the stop event). Then the Execute method or methods do whatever needs to be done on those resources and the Close method is called from the post-sequence step and closes all resources as well as sets the quit event for the deamon.

Rolf Kalbermatter

Link to comment

We probably did :rolleyes:.

Well there is another solution although it is in fact in a sense a global too. And your original solution with the IMAQ ref already goes a long way into that direction.

Make that VI an Action Engine or as I call them an intelligent Global with a method selector. Calling the Init method from the pre-sequence where it does the opening of the resources (and that deamon stays in memory polling the same or another Intelligent Global for the stop event). Then the Execute method or methods do whatever needs to be done on those resources and the Close method is called from the post-sequence step and closes all resources as well as sets the quit event for the deamon.

Rolf Kalbermatter

Indeed.

In fact you can have the best of both worlds (an "Inteliigent Global Daemon" if you like). If you make the Intelligent Global/Action Engine re-entrant and "share clone instances". You can have a boolean control that causes it either to continue running or exit immediately but it only has one dataspace. It means the first time you call it you set it false (runs as a daemon cos its connected to the conditional terminal) and you can still call it in other areas with the boolean set to "True" to retrieve/set the data. Used sparingly its very useful.

Hmmm. That sort of solves the OPs problem really.:frusty:

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.