03-27-2025 12:34 PM
I'm having difficulty with queues and notifiers that are members of a cluster. I'm not sure if queues and notifiers can be member of cluster. Is there something particular I need to do if a queue is to be part of a cluster? If I pass the cluster to a sub VI does it pass by reference or is a copy being made? Copying the queue every time I pass the cluster around isn't good. There are moments when the queues appear to work and others when I get errors. I'm thinking it may have to do with how the queues are instantiated. Now that I'm posting this, I'm not getting any error to capture and display, but I suspect they will come back.
03-27-2025 12:58 PM
There should be no problem with queues and notifiers in clusters. Note that queue wires and notifier wires are references; they don't contain the data.
The problem must be something else in your code (probably a race condition).
Post your code (LV 2020 or earlier), and a lot of people will look at it.
03-27-2025 01:00 PM
Queues and Notifiers are already passed as references. You should have no issues on them being in clusters. I suspect you are having lifetime issues, but we really need to see code to evaluate issues you may be having.
03-27-2025 01:09 PM
Queue variables are references to a queue. Variables passed to subVI's are by-value, but the value of a queue variable IS a reference, so you will not duplicate the queue when you pass it down.
The risks with this is managing the lifetime of the queue. If you obtain a queue then split the wire it generates, then releasing the queue on EITHER wire will release the reference for BOTH wires.
Also, depending on what you are doing, you need to be careful splitting that wire. Queues are generally a "many to one" or "one to one" tool. If you split the wire and have multiple dequeues, then each enqueued element will only come out of one Dequeue Element function. This can be helpful if you want it to work that way- for example, you're crunching a lot of data and want to use parallel processes. However, if you want two different things to get copies of the same data, you can't use separate Dequeues to do that. (use User Events in that case).
If you're splitting the wire to Enqueue elements, then that's all fine. They will stack up in the order in which they're received.
One last thought, if you're dynamically launching subVI's, then sometimes references can get automatically cleaned up when the top-level VI that obtained the initial reference closes. I can't recall offhand if queues do this or not, but it's something of an edge case. Obtaining queues and using them in a different top-level VI context isn't something you're likely to do accidentally 🙂
03-28-2025 04:37 AM - edited 03-28-2025 04:38 AM
@BertMcMahan wrote:
One last thought, if you're dynamically launching subVI's, then sometimes references can get automatically cleaned up when the top-level VI that obtained the initial reference closes. I can't recall offhand if queues do this or not, but it's something of an edge case. Obtaining queues and using them in a different top-level VI context isn't something you're likely to do accidentally 🙂
This is probably the single most issue encountered by intermediate users starting to write more complex applications when dealing with LabVIEW Refnums. Any LabVIEW refnum (both dark green as well as purple wires) is a reference to some underlying object. No copy of that object happens when you split a refnum wire nor when you open a new refnum to the same named object (when using names).
However, LabVIEW remembers in which top level hierarchy a refnum was created (open, create and similar) and when that top level VI goes idle (stops executing), all refnums created in the hierarchy of that top level VI are automatically closed. This is a sort of garbage collection.
If you happen to create a refnum in some VI hierarchy and then pass its refnum to another (usually dynamically started) VI hierarchy, that refnum gets "garbage collected" as soon as the first hierarchy gets idle, and is consequently also invalid in the other.
There are two approaches to avoid this problem:
1) Make sure that a refnum object is created in the hierarchy it is used, or keep the creating VI hierarchy running until it is not used in another VI hierarchy anymore.
2) For objects which allow names such as queues or notifiers, obtain an explicit refnum by name in every VI hierarchy. The two (or more) refnums still reference the same object but are individual refnums that each are registered to their respective top level VI hierarchy and only that respective refnum gets collected when one of the top level VIs goes idle. The actual object uses internally reference counting to remember how many individual refnums are referencing it and the object only gets destroyed when the last refnum is collected or closed.
03-28-2025 07:47 AM
Thank you. Knowing that placing queues and notifiers inside the cluster shouldn't be a problem and that they are references tells me that my approach is fine, but the problem is somewhere else.
03-28-2025 07:51 AM
Thanks. The process is linear. Only one piece of the code is acting on the queue at a time, but I use sub VIs to encapsulate functions and not clutter my top level VI with a maze of wires. This is also why I use clusters so I can move a bunch of information around with a single connection.
03-28-2025 08:43 AM
So, since queues should work in clusters, I put the queue back into the cluster and got the error below when I try to act on the queue. I don't get any error when I try to create the queue. I don't have any problems when I create the queue outside the cluster and use the external version. Any ideas?
03-28-2025 09:24 AM - edited 03-28-2025 09:26 AM
@Jim12345678 wrote:
I don't get any error when I try to create the queue. I don't have any problems when I create the queue outside the cluster and use the external version. Any ideas?
Not really without seeing the actual code, and I don't mean just the VI where you put the refnum in a cluster but also where you use it and how the two routines are related and get started.
My bet is still on that you are creating the refnum in a different top level hierarchy than where you try to use it. Personally I'm anyhow not a big proponent of putting all this stuff into big dinosaurs clusters.
Another point: your "read local, update element in cluster, write back to local" only is NOT a race condition if there is a 100% guarantee that nobody else in your program can at this point do a similar read/modify/write cycle on that same local. Basically, use of a local in such a way is exactly the same than if you used a global, the global just gives other VIs a chance to mess with the contents too, so amplifies the race condition problem.
03-28-2025 10:44 AM
Can you post all of your code? I would agree that the problem here is likely local variable related. I bet you're either reading the "Camera 0 Settings" local variable before it gets written (accidentally).
Another possible idea, are you using "Force destroy" on a duplicate wire somewhere? You're using named queues, meaning you CAN have multiple references to them, but if you use "force destroy" on one reference it will invalidate all references.