05-23-2014 07:21 PM - edited 05-23-2014 07:26 PM
Hi!
Summary of issue: I have attempted to use local variables and shift registers to pass .NET assembly references (or are they object instance references?) between two states of a state machine. This does not work, and I need your kind help understanding why. I am going to give as much detail as I can, because I don't necessarily know what everything's name is.
I am writing a state machine (I directly modified the LabVIEW example) in LV 2010 SP1. This state machine is simple and communicates with one instrument over USB. There are two .NET assemblies required for communication with this instrument. I have them sitting at the same level as the .vi file and its project. Here they are as seen in Windows Explorer. Ain't they cute?
I have a "Find Device" case, a "Perform Test" case and a "Finished Testing" case (as well as all the others, like the initialization case, the idle case and other things not relevant to this post). In "Find Device", I call the initialization VI that the instrument manufacturer provided and then proceed to set up the device. Here is that Initialize.vi:
Inside the VI is a series of method calls that set everything up and ultimately return an array of strings with the Device Keys of the discovered instruments. I want to call your attention to the two teal-coloured lines coming out of these constructors, which is how everything starts. These are references to a DeviceIOLib object and a CmdLib6800 object. Is that correct? I am going to go with that nomenclature for now.
Back to my "Find Device" case. If I wire every device VI with their required CmdLib6800 reference and the right DeviceKey string, every single instrument VI in this "Find Device" case is happy and the device functions well.
Trouble starts when I want to move over to the "Perform Test" case. I thought I'd be smart and use local variables (yes, I am in control of potential race conditions. My state machine is very simple!), like so:
And then, once the "Find Device" case is finished and I pop into the "Perform Test" case, and read the object reference and DeviceKey (please ignore breakpoint/probe):
That's where the fun starts. The very first VI that gets passed this reference from the local variable (the one seen above) fails with an error. Inside that VI is the following:
I have placed a probe on the error line of the invoke node, and here's what it says:
For the benefit of those searching the forum later, here is the text:
Error 1172 occurred at Error calling method [REDACTED].CmdLib6800.GetOutputEnable, (System.ArgumentNullException: Key cannot be null. Parameter name: key) Possible reason(s): LabVIEW: A .NET exception occurred in an external assembly. For information about correcting this error, copy the following exception (in bold), and search the Microsoft Developer Network (MSDN) Web site or the Web for a possible explanation. System.ArgumentNullException in GetOutputEnable_6800.vi
I am assuming that this means that my local variable trick didn't work. As a quick workaround (because this program is due in five days, what else is new... 😕 ) I tried wiring these teal-coloured lines from the "Find Device" to the state machine's outside while loop, and added a shift register. I then tried reading them back into the "Perform Test" case, but that did not work either.
Could you fine folks please help me understand:
Inside each of these VIs there is just an invoke node calling a shutdown method, but no explicit LabVIEW VIs from the .NET panel to close out the references—though I have no idea if that is necessary.
Anyway, that is my issue and I hope I have made it clear and easy to read. I would really appreciate your help and guidance.
Thanks!
Solved! Go to Solution.
05-25-2014 08:30 AM
@paulwb wrote:
I am assuming that this means that my local variable trick didn't work. As a quick workaround (because this program is due in five days, what else is new... 😕 ) I tried wiring these teal-coloured lines from the "Find Device" to the state machine's outside while loop, and added a shift register. I then tried reading them back into the "Perform Test" case, but that did not work either.
I would suspect that your bug is something like calling your cases in the wrong order, or calling some other case that overwrites the variable with a null reference. There is no reason why shift registers or local variables wouldn't work in passing a reference.
05-25-2014 01:54 PM
@drjdpowell wrote:
@paulwb wrote:
I am assuming that this means that my local variable trick didn't work. As a quick workaround (because this program is due in five days, what else is new... 😕 ) I tried wiring these teal-coloured lines from the "Find Device" to the state machine's outside while loop, and added a shift register. I then tried reading them back into the "Perform Test" case, but that did not work either.
I would suspect that your bug is something like calling your cases in the wrong order, or calling some other case that overwrites the variable with a null reference. There is no reason why shift registers or local variables wouldn't work in passing a reference.
Thank you for your reply. When I get back to work on Tuesday I will check to see if this is the case, but I thought I had checked for this already. Mainly what I was hoping for information on is whether my technique is valid, and you say it is, so I'm still puzzled.
On a related note, how would I blank out these references on purpose? Perhaps there is a null reference element I can place on the block diagram (I don't have LV at home to check, sorry).
05-25-2014 03:27 PM - edited 05-25-2014 03:29 PM
@paulwb wrote:
@drjdpowell wrote:
@paulwb wrote:
I am assuming that this means that my local variable trick didn't work. As a quick workaround (because this program is due in five days, what else is new... 😕 ) I tried wiring these teal-coloured lines from the "Find Device" to the state machine's outside while loop, and added a shift register. I then tried reading them back into the "Perform Test" case, but that did not work either.
I would suspect that your bug is something like calling your cases in the wrong order, or calling some other case that overwrites the variable with a null reference. There is no reason why shift registers or local variables wouldn't work in passing a reference.
Thank you for your reply. When I get back to work on Tuesday I will check to see if this is the case, but I thought I had checked for this already. Mainly what I was hoping for information on is whether my technique is valid, and you say it is, so I'm still puzzled.
On a related note, how would I blank out these references on purpose? Perhaps there is a null reference element I can place on the block diagram (I don't have LV at home to check, sorry).
A few comments from me:
05-26-2014 03:01 AM
In my experience 1172 is _some_ .net error, often some help/config-object needs to be created. If that applies in your case i dont know, but worth a check.
/Y
05-30-2014 03:51 PM
Thank you, tyk007 and Yamaeda. The error indeed turned out not to be related to my use of local variables with object references. It was due to the fact that I was using a Device_Write method for a couple of hand-crafted instructions (instead of the pre-packaged instruction VIs) when I should have been using Device_Query. As a result, the instrument and the controlling library were getting out of sync (I wasn't clearing the output buffer with a read following my write), and the method call for subsequent query commands would throw an error when the library didn't get the type of response it was expecting ('OK' instead of a number, for example). I figured this out with help from the original instrument VI developer, suggesting I check the log file that this library can optionally create.
Thank you everyone for your help!