09-07-2012 11:10 AM
I actually have two questions regarding XControls
1) What is the best way to have the internal state of an XControl be something when say, you bring the XControl into a new vi or project. At first I thought, oh I'll just set the default values for the indicator and control in the Init function but these seem to be reset in many circumstances. Is the only way to do this to make a constant and load the values that way? Where should I put this default state?
2) I've noticed that sometimes my property node calls happen before data writes to my XControl indicator. Specifically, if I have a sequence and in the first part of the sequence, I write to the indicator and then in the second area of the sequence, I update some property, I find that the property sometimes is updated first. This is important since there is an interaction between the current value and the property in question (i.e. it should be sufficient to say that the order matters). How does Labview update these things and why are they sometimes out of order (of course when I debug or highlight execution, the indicator works).
Any ideas?
Thanks!
09-07-2012 11:30 AM
1) Could you provide an example - how do you set values in Init and how they reset?
2) By default, writing data directly to indicator is asynchronous - it will send "command' to LabVIEW UI thread, and thread will process it when it will be ready (it may be busy feeding some front-panel Clastrosaurus elsewhere). Thats why writing to indicators is the quickest when it comes to code execution. If you want to ensure data will be "inside" your control right after writing it, use Value property node. Right-clicking and selecting Advanced->Synchronous Display will also make indicator to stop executing block diagram until data is actually updated.
09-07-2012 01:35 PM
1) So initially, I just set the indicator and control defaults and set them to what I wanted them to me (and then made them default in that vi). I assumed that they were read in the event that variant wasn't used (i.e. when a new XControl was placed). However, I made a source distribution and then made a new XControl in that source distribution. The default values weren't the same as in my original project. So when it initialized, it was just empty. I'm not entirely clear on the process that occurs, specifically why the defaults are forgotten, but also when a new XControl is dropped on the front panel of a new project. I assume Init is called to set the state and then the Facade is called? It's impossible to debug this sort of thing since you can't actually see the VI for the facade until after you've dropped the new XControl.
So the question becomes where do I store this default state information?
2) So writing to the indicator is more immediate than the property node? I find this hard to believe. So is it possible to say, in the first box of a sequence write a value to an indicator and in the second box of a sequence read the OLD value from the indicator. I'm not sure I've ever seen this behavior. Is it possible to see if a write is pending to the indicator when doing the property node call? That might help...
09-07-2012 02:25 PM
So regardless of whether Synchronous Display is set or not, the property node will always be called first in the example below unless I am highlight debugging the vi (Log Message is the XControl).
09-07-2012 05:49 PM
@majoris wrote:
1) So initially, I just set the indicator and control defaults and set them to what I wanted them to me (and then made them default in that vi). I assumed that they were read in the event that variant wasn't used (i.e. when a new XControl was placed). However, I made a source distribution and then made a new XControl in that source distribution. The default values weren't the same as in my original project. So when it initialized, it was just empty. I'm not entirely clear on the process that occurs, specifically why the defaults are forgotten, but also when a new XControl is dropped on the front panel of a new project. I assume Init is called to set the state and then the Facade is called? It's impossible to debug this sort of thing since you can't actually see the VI for the facade until after you've dropped the new XControl.
So the question becomes where do I store this default state information?
I'm attaching a chunk of code I've made some time ago to archieve similar thing you are trying to do.
Before I explain it, the life cycle of any xControl is:
- Init, when creating instance (dropping new xControl, opening FP with xControl) - this is where saved state is loaded.
- Facade, when working with xControl. From my observations, immediately after finishing with Init, event Exec State Change is fired in Facade (then -obviously- Timeout).
- Convert State For Save, when instance is closing. This VI is optional - it let you choose what data should actually be saved. You can as well do nothing with it (as it is done by default) and whole state will be saved.
- Uninit, as the final xControl call.
Everything here is perfectly debuggable - just place breakpoint wherever you want. I'm not sure why you say it's "impossible"?
Going back to my code: I let Init do its job. Then in Facade "Exec State Change" event I write data from loaded state into indicator
When data is changed in "File Path Control" val change event, I save it in state (remember to set "State Change" flag in Action wire below!).
And if you want to force some default values, you should put them into State in Init. Then just write the data into controls, as I did.
majoris wrote:2) So writing to the indicator is more immediate than the property node? I find this hard to believe. So is it possible to say, in the first box of a sequence write a value to an indicator and in the second box of a sequence read the OLD value from the indicator. I'm not sure I've ever seen this behavior. Is it possible to see if a write is pending to the indicator when doing the property node call? That might help...
I've been there too and I've become a believer (and learned a lot in process): http://forums.ni.com/t5/LabVIEW/Cursor-List-Property-error-1077/m-p/2007157#M659943
I'm not sure if exact behaviour (writing new data and getting old immediately) is possible - this is entirely up to UI thread, maybe it has some clever way to prevent this. Either way, you should watch out for calling properties/methods immediately after writing something to indicator, especially when working with xControls (they may introduce a little more overhead when updating value).
09-08-2012 12:58 PM
"Everything here is perfectly debuggable - just place breakpoint wherever you want. I'm not sure why you say it's "impossible"?"
When you first drop the XControl, Labview makes an instance of the Facade vi. I'm not aware of a way to have this instance open prior to dropping the XControl. Instead, you drop the XControl but by the time you interact with the Labview UI again, it's gone through the process of initializing the XControl! However, if it does call Init, I suppose you can but a breakpoint there and you might be able to open up the Facade before it's called. However, I feel like if the UI is hanging on that breakpoint, I won't be able to do it. Also, I think the first thing it calls isn't a Exec State Change but a Data State Change (per the documentation, though I haven't checked this). Anyways, I'll check this out.
I'm still not 100% sure how to save the default state. Should I make the controls for the default state in Init constants to prevent them from being changed when I distribute the source. Maybe this is the safest route. Anyways, it's been very confusing. I almost want to put the default state in a XML file or something but that would be super lame to have to load a file everytime the XControl is copied.
Overall, this behavior is kinda annoying, but I guess I can deal with it. In the end, it makes my XControl less usable than I want it to be. And given that you can hang the UI fairly easily by making a debug error with XControls, I'll probably avoid them altogether in the future.
09-08-2012 04:10 PM
@majoris wrote:
"Everything here is perfectly debuggable - just place breakpoint wherever you want. I'm not sure why you say it's "impossible"?"
When you first drop the XControl, Labview makes an instance of the Facade vi. I'm not aware of a way to have this instance open prior to dropping the XControl. Instead, you drop the XControl but by the time you interact with the Labview UI again, it's gone through the process of initializing the XControl! However, if it does call Init, I suppose you can but a breakpoint there and you might be able to open up the Facade before it's called. However, I feel like if the UI is hanging on that breakpoint, I won't be able to do it. Also, I think the first thing it calls isn't a Exec State Change but a Data State Change (per the documentation, though I haven't checked this). Anyways, I'll check this out.
Put breakpoint on any wire "entering" bd of Facade and LV will stop as soon as Facade is first called. I don't see any reason to open Facade before this. Init is called once and only once when instance is created. Furthermore, only Facade is reentrant VI - others are not, so Init will be called as many times as the number of xControl instances are created.
@majoris wrote:
Should I make the controls for the default state in Init constants to prevent them from being changed when I distribute the source. Maybe this is the safest route.
Exactly. Put default values into State in Init, then write them to controls when Facade is first called. Thats perfectly valid and safe way.