LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Writing only to certain cluster elements in an array by reference

Solved!
Go to solution

Hi,

 

I have an array of clusters that I use both to display and to enter data, i.e. some cluster elements are non-editable (disabled) controls used as "fake" indicators (numerics, strings, LEDs) and some are normal controls (numerics, buttons).

The "indicator" part of this array of clusters needs to be permanently updated (e.g. with positions of motors), normally by replacing the according cluster elements in a for loop and writing back to the array. This can lead to race conditions with the "control" part: if the user enters data into the control at a "bad" timing, it gets immediately overwritten with the old value - in this case the update procedure started just before the user input and ended right after the user input (which can be just a click), so the old values of the controls are written back to the controls, since the array has to be written back as a whole.

 

Now I'm looking for a solution to this race condition without changing this "mixed" control/indicator approach (e.g. by separate indicator and control arrays next to each other and coupled scrolling or so - that would make the GUI design much more horrible, among other disadvantages). I know it's possible to change the value of a cluster element without having to rewrite the whole cluster by using the element's reference. However, that's more tricky if you have an array of clusters, because you are looking for the cluster at a certain array index and to my knowledge there's no such property that gives you e.g. the reference to the array element at a certain index (which is a long-time lack in Labview's array handling). If you change the "value" property of a cluster element within an array, it seems to affect the "last active" array element, at least it correlates with the array element that has been clicked on last. Maybe there's a way to somehow programmatically set that "last active" array element and browse through the array this way (setting the corresponding "indicator" cluster elements by reference) or maybe someone knows a "nice" and elegant solution?

I hope you understand what I mean 😉

 

Thanks in advance!

0 Kudos
Message 1 of 7
(6,689 Views)
Look at data value references or a FGV with a set of VIs for an API to the things you need to do.
=====================
LabVIEW 2012


0 Kudos
Message 2 of 7
(6,672 Views)

We probably need to see some code.

 

I often use arrays of "mixed" clusters (some elements disabled and used as indicators while others are used as controls) and I never experienced any race conditions. I typically use events to detect value changes by the user, find the changed element by comparing the old a new value form the event data node, and then use the in place elements structure  to recalculate and update the changed elements right inside that same event case.

0 Kudos
Message 3 of 7
(6,671 Views)
Solution
Accepted by topic author Novgorod

To prevent such race conditions, make sure you write to the array only in the same place you change it and only write the indicators data. Practically, this means that if you have a value change event for the control, you should have another event case in the same structure for updating the indicators (either a user event or the timeout) and make sure that the indicator event takes the rest of the data from the current value (e.g. through a terminal or a local variable or the DVR Steve suggested). Likewise, you can use the control terminal to take the current value from the control for the indicators instead of relying on the event holding the correct value.


___________________
Try to take over the world!
0 Kudos
Message 4 of 7
(6,665 Views)

Thanks for the comments!

 

@altenbach:

I'm doing more or less the same apart from writing the array back to itself upon a value change event (that would be too straight forward :D), but I think that might be the solution!

I've attached a very minimalistic simulation of the problem (mixed_control_update.vi): The indicator "update" happens in the timeout case and takes some time (i.e. low update rate). If you try to change the controls (e.g. click the increment/decrement buttons), you will see old values popping back up from time to time. It doesn't matter whether the update is done like in the example (straight forward by indexing the array and bundling the new indicator value) or with shift registers and in-place-element structures (that's just a memory/performance thing, I think).

Now in the 2nd example, there's an additional value change event case which simply writes the changed array back to itself and this seems to work (though the updated indicator values are not displayed as long as you edit the control, but that's fine)...

 

In my original program I also do stuff in the value change case, but I didn't think of simply writing the new value back to the array 😉

Let's see whether it works out...

 

@SteveChandler:

Though the problem might be solved without doing fancy stuff with references, I'm still interested whether my original idea of fixing this problem would be possible. Could you elaborate a bit more on how to use data value references to modify/update particular array/cluster elements inside front panel objects (controls/indicators)? The little information I find about it from official sources tells me that it's just a memory optimization feature...

Download All
0 Kudos
Message 5 of 7
(6,641 Views)
 

@SteveChandler:

Though the problem might be solved without doing fancy stuff with references, I'm still interested whether my original idea of fixing this problem would be possible. Could you elaborate a bit more on how to use data value references to modify/update particular array/cluster elements inside front panel objects (controls/indicators)? The little information I find about it from official sources tells me that it's just a memory optimization feature...


When I said FGV or DVR it was because I tend to use DVRs these days where I once used FGVs. Someone should write a nugget on that.

 

Except for very simple cases like what you show, I never store the actual data in the GUI. I would create a FGV that has a collection of VIs that access it for each of the things that I need to do with the data. I never directly access the FGV in any code other than these "API" VIs. I once wrote a nugget on that.

 

In your case I would probably have at least the following:

 

  • Initialize. Only error in and error out. Initializes the FGV to an empty array.
  • Get All. Returns the array of clusters
  • Write. Appends to the array of clusters in the FGV.
  • Read. Input is the index you want, output is the element.
  • Update Element. Input is a cluster of controls and index. Calls the replace array element method of the FGV.

You will probably want other methods that are called by whatever code writes the "fake indicator" values for example.

 

Again, in a simple application all of this is probably overkill. But if you do it this way you will be glad you did when someone wants additional functionality. It is also VERY helpful when you want to do something like limit the range of values for one of the controls. You could do that with a control property but you run into a wall if each element of the array has it's own range of values. Also you could do something like have an out of range indication for each "fake indicator" element of the array.

 

Having said all of that, once you start designing in this way, you really are doing object oriented programming and you may as well create a class.

=====================
LabVIEW 2012


0 Kudos
Message 6 of 7
(6,613 Views)

Ok, then I've misunderstood what you meant initially - you're talking about data abstraction, not manipulating a GUI element.. Surely that sounds like a clean and systematic way for handling the data, also a bit overkill for this particular GUI element 😉 - I use a quite similar approach e.g. for communicating with hardware devices (motors etc.)..

 

What I was describing is actually a "GUI problem", so an underlying FGV structure wouldn't eliminate the need to update the "fake indicator" on the GUI and to input control values in the same GUI object, since the FGV is "just" another layer of abstraction.. The race condition with editing/updating the GUI element could be satisfactory resolved with altenbach's suggestion of writing back to the GUI element on a value change event (see my last post) - thanks for the advice!

0 Kudos
Message 7 of 7
(6,603 Views)