LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

What does "refnum not valid in this context" mean andwhat are the ground rules for when a queue refernce is valid or not?

Solved!
Go to solution

"Refnum not valid in this context" --- I used the word 'context' for this string. My mistake. It should have been "Refnum not valid in this application instance". I am fixing this text for LV 2010.

 

Short answer: Inside LV R&D, we use  the term "context" interchangeably with "application instance". I forgot that "context" is an internal-only term when I typed the error message.

 

Long answer: This error occurs when you do Obtain in application instance A and then try to use that refnum in application instance B. Two application instances on the same machine are meant to operate the same as if they were on two separate machines. Let's take queues as an example. You cannot use queues to communicate between machines, and so you cannot use them to communicate between two application instances on the same machine. We enforce this blockade for all refnums. This makes it so that any code you write on a single machine for communication between two app instances, say a client and a server, is guaranteed to work the same when you move the client and the server to different machines. 

 

If you were actually on two separate machines, if you opened a refnum in app instance A and then passed that number across to app instance B and tried to use it, you'd get an "invalid refnum" error.  But when you're on the same machine, we can see that the refnum is valid, but we also can see which app instance the refnum was opened in and thus report it as invalid in any other app instance. 

 

If you need to communicate between two contexts, you need to use a mechanism that works for communication between two machines -- such as opening an app instance refnum and using VI Server, or using the TCP/IP primitives.

 

Message 21 of 47
(4,074 Views)
I've answered the original basic quesiton, but the rest of the thread spawned more questions and DFGray has asked me to prep a more complete answer to some of them. I'll try to get this posted before I leave work this evening.
Message 22 of 47
(4,070 Views)

Aristos Queue wrote:

"Refnum not valid in this context" --- I used the word 'context' for this string. My mistake. It should have been "Refnum not valid in this application instance". I am fixing this text for LV 2010.

 

Short answer: Inside LV R&D, we use  the term "context" interchangeably with "application instance". I forgot that "context" is an internal-only term when I typed the error message.

 

Long answer: This error occurs when you do Obtain in application instance A and then try to use that refnum in application instance B. Two application instances on the same machine are meant to operate the same as if they were on two separate machines. Let's take queues as an example. You cannot use queues to communicate between machines, and so you cannot use them to communicate between two application instances on the same machine. We enforce this blockade for all refnums. This makes it so that any code you write on a single machine for communication between two app instances, say a client and a server, is guaranteed to work the same when you move the client and the server to different machines. 

 

If you were actually on two separate machines, if you opened a refnum in app instance A and then passed that number across to app instance B and tried to use it, you'd get an "invalid refnum" error.  But when you're on the same machine, we can see that the refnum is valid, but we also can see which app instance the refnum was opened in and thus report it as invalid in any other app instance. 

 

If you need to communicate between two contexts, you need to use a mechanism that works for communication between two machines -- such as opening an app instance refnum and using VI Server, or using the TCP/IP primitives.

 


 

Thank you Aristos Queue!

 

I am very sorry you had to be the one to reply to this thread since I was trying get an answer without bugging you.

 

I think I follow most of your reply.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 23 of 47
(4,065 Views)

Please refer to my image above...

 

Why not the same text in "A" "B" and "D"?

 

Different authors?

 

I just double checked the other thing that was confusing me and it turns out the code was tricking me and getting the ref inside the Template (Fooled by own robust code Smiley Mad ) when it checked if the queue ref was valid inside the template.

 

I do have what is starting to feel like a firm idea that I can take a chance* on remebering.

 

Ben

 

* As you get old, the more distance memories fade such that they can become difficult to distinguish from very vivid memories. Similarly with learning stuff the wrong way.

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 24 of 47
(4,053 Views)
Solution
Accepted by Ben

Ben wrote:

Thank you Aristos Queue!

 

I am very sorry you had to be the one to reply to this thread since I was trying get an answer without bugging you.

 


It's ok. This is my area of expertise (thus my user name), so it makes sense that I end up getting this question. The queue and notifier primitives were the first feature I wrote for LV back in LV6.1 and I've maintained them ever since. 

 

And with that... on to the rest of the questions:

 

Ben wrote:
What code/project context foreces/uses multiple context?

 

Application instances (sometimes accidentally called "contexts" by R&D folks) are islolated instances of LabVIEW. Prior to LabVIEW 8.0, this meant a separate labview.exe or built application using lvrt.dll. Nowadays, we can have multiple application instances within the same labview.exe or built application. These separate app instances are boxes: the VIs inside one box do not know about and cannot directly interact with the VIs in another box. The only ways to communicate between two different boxes are the same features of LabVIEW that allow communication with another physical machine. Among these features are the Open App Instance primitive, the TCP/IP primitives and the Network Shared Variable. There are others. Generally, a feature can be used for communication between app instances if and only if it takes a port number or URL as part of its setup. Queues, notifiers, data value references, and file refnums (to name a few) do not, so you know they are only for communication within the context. 

 

Ben wrote:
What I am looking for ideally is a white paper that has not been written yet that describes each of the process contexts that we should expect our code to run in and when and under what circumstances these contexts are used.
 

If you open VIs without opening a project (.lvproj file), those VIs open in the "main LabVIEW app instance" or "default app instance".

 

If you open a project, the VIs under "My Computer" in that project will all be in their own app instance. Thus if you have two projects open, the VIs in each project are isolated from each other. That's how you can have two VIs of exactly the same name in memory simultaneously -- if each one is in a different project, they are in separate app instances.

 

A project can have multiple targets (FPGA, RT, PDA, etc). Each target is a separate app instance.

 

AND THAT'S IT. There are other private app instances created inside the LV editor -- isolated boxes where LV runs VIs that are part of LV itself. For example, a lot of the Project Window's functionality is written in G, but if you ask for "All VIs In Memory", you won't see all the VIs that are part of the project... those VIs run in an isolated app instance, and the "All VIs In Memory" method returns the VIs only for the calling app instance. 

 

To the absolute best of my knowledge, no user feature other than the project automatically creates separate application instances for user-written VIs to run. There is a method that exists (and I *think* it is public for users to invoke) that can deliberately create a new app instance, but if you're not invoking that explicitly, then the app instance in which your VIs run should *always* be the app instance it is loaded in (i.e., the project app instance or default app instance).

 

Which raises the question: why is Ben seeing this error? I have no idea at this time. 

 

DFGray wrote:
Contexts are generally used by the LabVIEW team to hide running LabVIEW code so it is not an annoyance.  For example, the FPGA Wizard, a LabVIEW application, runs in a separate context to prevent its hundreds of VIs from showing up in the VI hierarchy, causing more than a minor annoyance.  LabVIEW has several standard contexts for this purpose.

 

Project and target isolation are the other use cases for app instances. LabVIEW also creates temporary app instances for actions such as Build Application, where we may load a copy of user VIs in order to modify them (operations such as "disconnect typedefs") before building them into the EXE. The isolation of the boxes keeps us from modifying the original user VIs in the project app instance.

 

Robbob wrote:
NI does not recommend typecasting references unless you are very familiar with the underlying data, as it is easy to make mistakes.

 

In general, LabVIEW should never crash if LV R&D has done its job right. There are  two exceptions to this rule: your VI is calling out to a third-party piece of code that does something to cause a crash OR user uses Type Cast to cast one refnum into another type of refnum. Sometimes this works, sometimes it doesn't. The typecasting on refnums is intended to allow you to cast a refnum as an integer to use as a lookup key and then cast back to the same type of refnum when you're done using it. Unfortunately, you can cast them directly, and LV may or may not work right when you do this.

 

So when Robbob says "NI does not recommend typecasting references", I'd interpret this as "Use typecast to cast references to int32 and cast back to same refnum type, but never do anything else unless explicitly told 'this is safe' by someone who can see and understand the under-the-hood code of LabVIEW."

 


More in a little while... I'm putting together images for queues/typedefs/coercion dots.

 

Message 25 of 47
(4,054 Views)

Ben wrote:

Please refer to my image above...

 

Why not the same text in "A" "B" and "D"?


That looks like a bug. Can't prove it yet, but I'll (speculating off the top of my head) that the D probe is passing the context of the VI into the "to string" method, and so the refnum resolves as "unnamed", but the LV class probe is not passing the context of the VI into the "to string" method, and so the refnum resolves as "valid, but not in this context". 

Message 26 of 47
(4,047 Views)

Off Topic

 

Aristos,

 

Evrything wonderful that could be said about support has already been said about you and to you. How can I top that? How? I'm going to say an extra prayer just for you.

 

Thank you,

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 27 of 47
(4,037 Views)
Coercion dots/typedefs/queues

 

Short story: I would not in general typedef a queue. I would frequently typedef (or make a LV class) for the data inside the queue. A typedef is for a data type you expect to need to change or that you need to somehow differentiate from other types in the vicinity. It is pretty rare that you decide to swap your queue out for a notifier, and I cannot think of any other data type that you would ever even possibly swap it out for, so the "expect to change" reason doesn't apply. You might, in rare cases, have multiple queues that all carry the same underlying data and you want to be careful not to wire a refnum wire of one queue to a terminal of the other queue, so you make a typedef of the queue so that you get a coercion dot. That's reasonable, so it might happen, but rare, so I wouldn't generally do it.

 

One of the reasons that I wouldn't generally do it is that it requires either a coercion dot or the use of the Typecast node...

 

Ben wrote:
1) What is the "right way" to create queue ref that is linked to a type-def that does not use the Type Cast?


This may be too basic an intro for Ben, but I figure I'll be thorough.

 

Here are all the different types of controls that we're talking about in this thread:

 

 FrontPanel.png

 

It is easy to create queues of type C and 😧

ObtainQueue.PNG

If you create controls/indicators off of the top two wires, you'll get controls of type C and D respectively.

 

Ben wants to know how to create E and F. You can change C into E and D into F using the typecast node or coercion dots...

CanCast.PNG

 

Like this...

HowCast.PNG

 

For the record, you shouldn't cast queues whose underlying types are different. When in doubt, try using the Obtain Queue primitive to test the types:

ErrorObtain.PNG

If the second Obtain returns an error, don't try casting refnums of those types.  It might work. Then again... it might fail spectacularly or, worse, fail in a subtly wrong way. 

 

tst wrote:
Presumably you wouldn't get coercion dots if you didn't make the control a typedef, but instead allowed LV to take care of it by only having the queue data a typedef.
I can't say whether this is good practice, since there's no official documentation which says that a queue ref will adapt to the typedef that's inside it, but it seems to be a reasonable thing to expect and you know how to get NI not to drop support for it.

 

The preservation of the underlying typedef type is a designed feature of the queues. It's been that way since, oh, I don't know, a long time ago.

 

tst wrote:

They do get reflected or I would not have suggested it. I believe it began behaving this way since ~8.0.

 

I would've guessed LV 6.1, but you've made me doubt myself, so we'll go with 8.0 for now. 


tst wrote:
I don't remember for sure, but this may also work in older versions if you drag the typedef into the queue reference (you can see the queue type if you right click the reference and select "Show Control").
The problem with this, as I said, is that it's not documented, which means that you have to go against the good practice of making a distributed data type (the queue ref) a typedef without anything official to back you up.

 

I'm not sure what part isn't documented. You can drag any type onto the queue control/indicator to set the type of the queue's data, including typedefs.

 

I don't see anything wrong with not typedef'ing the queue, and I see not having to worry about maintaining that typedef and casting my obtained refnums over to that typedef as a positive.  And it creates one more .ctl file to worry about, a .ctl file that gives me no benefit, the way typdef'ing the underlying data might do. So, without further ado, I'll declare this "officially recommended practice". And that will last until someone gets burned by it...

 

Ben wrote:
Sometimes I wonder if we are inventing "good pratice" as we go by trial and error.

 

Yes, Ben. That's why we call you a "LabVIEW Champion." Remind me to add that explicitly to the Champion's Charter at next NI Week. "Heroically charges through pain and lost work and puts up with wishy-washy LV R&D answers in an ongoing quest to create ex nihilo recommended LV practices for other usersr." The heroic overtones and the use of Latin will make it sound more exciting for future champions. 🙂 

 

Message 28 of 47
(4,027 Views)

Aristos Wrote:

In general, LabVIEW should never crash if LV R&D has done its job right. There are  two exceptions to this rule: your VI is calling out to a third-party piece of code that does something to cause a crash OR user uses Type Cast to cast one refnum into another type of refnum. Sometimes this works, sometimes it doesn't. The typecasting on refnums is intended to allow you to cast a refnum as an integer to use as a lookup key and then cast back to the same type of refnum when you're done using it. Unfortunately, you can cast them directly, and LV may or may not work right when you do this.

 

So when Robbob says "NI does not recommend typecasting references", I'd interpret this as "Use typecast to cast references to int32 and cast back to same refnum type, but never do anything else unless explicitly told 'this is safe' by someone who can see and understand the under-the-hood code of LabVIEW."

 

Thank you for clarifying this much better than I could. I didn't think of the case where you would want to use a lookup key, very interesting. I just know in the past when typecasting refnums and running into issues, I was generally told 'Don't do that'

Rob K
Measurements Mechanical Engineer (C-Series, USB X-Series)
National Instruments
CompactRIO Developers Guide
CompactRIO Out of the Box Video
Message 29 of 47
(4,022 Views)

Robbob wrote: I didn't think of the case where you would want to use a lookup key, very interesting. I just know in the past when typecasting refnums and running into issues, I was generally told 'Don't do that'

Excellent advice. Pass it along to the next newbie. If that newbie someday needs casting, he or she will ask and someone will tell them about it at that point. Most LV users never do.

Message 30 of 47
(4,016 Views)