Daklu Posted July 24, 2008 Report Share Posted July 24, 2008 I have an application that needs to spawn a vi in a parallel process, have it stop when triggered, and return the last value from the spawned vi. (This is for the Start Toast and Stop Toast methods in my Toaster Base class.) I created a mock up to help figure this out. The first part wasn't too hard. I implemented the second part by having the spawned vi check the status of a Func Global. I'm not sure how to do the last part though. I've seen a few mentions of weakly typed references, strongly typed references, and call by reference nodes on the forums and in Labview help, but I haven't found anything that points me down the path of putting it all together. Clues? Hints? Quote Link to comment
Francois Normandin Posted July 24, 2008 Report Share Posted July 24, 2008 QUOTE (Daklu @ Jul 22 2008, 07:03 PM) I have an application that needs to spawn a vi in a parallel process, have it stop when triggered, and return the last value from the spawned vi. (This is for the Start Toast and Stop Toast methods in my Toaster Base class.) I created a mock up to help figure this out. The first part wasn't too hard. I implemented the second part by having the spawned vi check the status of a Func Global. I'm not sure how to do the last part though. I've seen a few mentions of weakly typed references, strongly typed references, and call by reference nodes on the forums and in Labview help, but I haven't found anything that points me down the path of putting it all together. Clues? Hints? You can use the method "Get Control Value" to recuperate a certain value from your dynamically loaded VI. Wire the label name of your control/indicator to get a Variant of its current value. However, the code you display might not work all the time... It will work if the diagram of your dynamically loaded VI loads in memory completely before you dispose of the reference. I suggest you do not close the reference since you took care of wiring the "Auto Dispose Ref" to TRUE. This is sufficient to ensure your dynamically loaded VI will continue running even if the caller aborts. Opening it's front panel AND wiring Auto Dispose Ref is exactly what you need. Closing the reference might put you in trouble...Check out Christina's Eyes on VIs about VI server for more in-depth explanation of this behavior. Quote Link to comment
Daklu Posted July 24, 2008 Author Report Share Posted July 24, 2008 QUOTE (normandinf @ Jul 22 2008, 05:34 PM) However, the code you display might not work all the time... It will work if the diagram of your dynamically loaded VI loads in memory completely before you dispose of the reference. I suggest you do not close the reference since you took care of wiring the "Auto Dispose Ref" to TRUE. This is sufficient to ensure your dynamically loaded VI will continue running even if the caller aborts. Opening it's front panel AND wiring Auto Dispose Ref is exactly what you need. Closing the reference might put you in trouble...Check out http://eyesonvis.blogspot.com/2008/03/vi-server-references.html' rel='nofollow' target="_blank">Christina's Eyes on VIs about VI server for more in-depth explanation of this behavior. Thanks for the tips Norm. If I understood Christina's blog correctly the reason my mock-up works is because the front panel is opened while the VI is running. In my real code it will not be open so it would have shut down immediately. I would have been pulling my hair out over that one. QUOTE You can use the method "Get Control Value" to recuperate a certain value from your dynamically loaded VI. Wire the label name of your control/indicator to get a Variant of its current value. After pondering it a bit more I think I'm going to load a reference to the dynamic vi at program start and maintain it until program shut down. There should only be a single instance of the vi at any time so I think doing that will simplify things a bit, plus save me some time by not opening and closing a reference several times. To do this I'd wire FALSE into Auto-Dispose and use Close Reference when my main app shuts down, correct? Let me make sure I understand the implications of your suggestion... I use "Get Control Value" in my main vi with a reference to the spawned vi wired into it. Since my main app doesn't know when the spawned vi stops, it will need to poll Get Control Value until it sees the values are no longer changing. (Or I could just put a "Stopped?" boolean indicator on the connection pane.) Tangential question: Suppose the spawned vi was storing data in a buffer and I wanted to periodically read and empty the buffer. I don't suppose there's a way for the spawned vi to know when it's indicator has been read? (Maybe I could use a "Trigger" control on the spawned vi that would place the collected data on a buffer indicator. I don't have LV right in front of me but I assume there is a "Set Control Value" prim?) Quote Link to comment
Norm Kirchner Posted July 24, 2008 Report Share Posted July 24, 2008 It sounds like you're about to head down the suggested path, but before you get too far you may want to think about "LVx - Exported Functions" that will give you almost this functionality but even more. http://forums.lavag.org/LVx-Exported-LV-Fu...lity-t9437.html By setting up an exported function to stop the VI, you can have the stopping VI return it's data through the existing process within LVx. This will also work w/ multiple cloned clients. Quote Link to comment
Daklu Posted July 24, 2008 Author Report Share Posted July 24, 2008 QUOTE (Norm Kirchner @ Jul 23 2008, 08:03 AM) It sounds like you're about to head down the suggested path, but before you get too far you may want to think about "LVx - Exported Functions" that will give you almost this functionality but even more. Yikes! I downloaded the demo you posted... I'm not even smart enough to figure out what it's supposed to do, much less code something like that. Even if I could figure it out, our "developers" aren't knowledgeable enough to maintain or modify an application using that kind of infrastructure. (I have a hard enough time trying to get people to use Labview projects... A "state machine?" What's that?) Quote Link to comment
eaolson Posted July 24, 2008 Report Share Posted July 24, 2008 QUOTE (normandinf @ Jul 22 2008, 07:34 PM) You can use the method "Get Control Value" to recuperate a certain value from your dynamically loaded VI. Wire the label name of your control/indicator to get a Variant of its current value. The problem with that is the indicator won't be updated until the dynamic VI finishes and you're not exactly sure when that will be. So Get Control Value may return the initial value or the final value depending on when you call it. I would suggest using a notifier to pass out the value that you want. You need to give the dynamic VI the notifier, which adds an extra step, have the dynamic VI put the correct value in the notifier, then just wait in the top level VI for the notifier to be populated with a value. Quote Link to comment
Francois Normandin Posted July 24, 2008 Report Share Posted July 24, 2008 QUOTE (Daklu @ Jul 23 2008, 10:25 AM) I don't have LV right in front of me but I assume there is a "Set Control Value" prim?) You're quite right about that! QUOTE (Daklu @ Jul 23 2008, 10:25 AM) To do this I'd wire FALSE into Auto-Dispose and use Close Reference when my main app shuts down, correct? Or leave Auto-Dispose unwired... default is False. QUOTE (Daklu @ Jul 23 2008, 10:25 AM) Let me make sure I understand the implications of your suggestion... I use "Get Control Value" in my main vi with a reference to the spawned vi wired into it. Since my main app doesn't know when the spawned vi stops, it will need to poll Get Control Value until it sees the values are no longer changing. (Or I could just put a "Stopped?" boolean indicator on the connection pane.) Yes, but that's inefficient... (see below for other suggestion) QUOTE (Daklu @ Jul 23 2008, 10:25 AM) Tangential question: Suppose the spawned vi was storing data in a buffer and I wanted to periodically read and empty the buffer. I don't suppose there's a way for the spawned vi to know when it's indicator has been read? (Maybe I could use a "Trigger" control on the spawned vi that would place the collected data on a buffer indicator. I think you should consider using Register Events functionality. I'm not familiar with this too much so I could be wrong, but that's the avenue I'd explore if I were in your context. That would go like this: a) Register an event in your main VI. b) Pass the Event reference to the dynamically loaded VI using "Set Control Value" method. c) When your dynamically loaded VI produces the data, it triggers the event programmatically. d) Your Main App will register the event occurence and use "Get Control Value" method to get data from dynamically loaded VI. An alternative way would be to have a queue... Much simpler but harder to debug. Start a queue and pass Queue Name or Queue reference to your Dyn. Loaded VI to add data. Read Queue Status in your Main App to get data. EDIT: eaolson's suggestion is similar to Queue, but I realize it's much simpler! :thumbup: Quote Link to comment
Daklu Posted July 24, 2008 Author Report Share Posted July 24, 2008 Your responses are great! They are getting fairly detailed so let me provide a bit more context to my problem... I have a Toaster class that reads data from a serial port. The methods I have (among others) to retrieve data are Start, Stop, and Read Buffer. Start will spawn a vi that continuously captures data and puts it in an array. Stop (obviously) stops the data capture process. Read Buffer retrieves the data that is in the buffer. For these methods I don't think I'll need a notifier as the main vi tells the spawned vi to stop. I also have "Read n" and "Read t" methods that captures n data packets and captures packets for t time respectively. These would benefit from the notifier I think. QUOTE I would suggest using a notifier to pass out the value that you want. You need to give the dynamic VI the notifier, which adds an extra step, have the dynamic VI put the correct value in the notifier, then just wait in the top level VI for the notifier to be populated with a value. Two questions: For this to work wouldn't I need to have a separate loop in the main vi dedicated to waiting for the notifier? Since my implementation is in a class, I don't have a main vi in my class to monitor the notification from the dynamic vi. How does that change things? I suppose ultimately I will have a main vi somewhere. I could create an "Enable Notification" method that accepts the notifier as an input. QUOTE The problem with that is the indicator won't be updated until the dynamic VI finishes and you're not exactly sure when that will be. So Get Control Value may return the initial value or the final value depending on when you call it. Isn't this resolved by putting the indicator in the data collection loop where it is continuously updated? QUOTE I believe I remember both Sciware GOOP and Tomi's OpenG LVOOP by-ref wrappers having actor VIs which communicate back this way. I'd love to learn how to use those packages, but right now using advanced addons such as those will create support issues in the long term. Although I suppose it does lend itself to a certain amount of job security... Quote Link to comment
Yair Posted July 24, 2008 Report Share Posted July 24, 2008 You might also wish to get the notifier by name in both places. By the way, there are already pieces of code which do this (other than Norm's, of course). I believe I remember both Sciware GOOP and Tomi's OpenG LVOOP by-ref wrappers having actor VIs which communicate back this way. Quote Link to comment
eaolson Posted July 24, 2008 Report Share Posted July 24, 2008 QUOTE (Daklu @ Jul 23 2008, 12:31 PM) I have a Toaster class that reads data from a serial port. The methods I have (among others) to retrieve data are Start, Stop, and Read Buffer. Start will spawn a vi that continuously captures data and puts it in an array. Stop (obviously) stops the data capture process. Read Buffer retrieves the data that is in the buffer. For these methods I don't think I'll need a notifier as the main vi tells the spawned vi to stop. It seems to me that this may be susceptible to race conditions. It sounds like you might have this sort of thing going on: 1. You run Start to begin data acquisition, which spawns a separate thread. That thread runs for a while. 2. You run Stop to tell the separate thread (the dynamic VI) to stop running. How does the dynamic VI know when to stop? 3. The dynamic VI notices that it's been told to stop, and actually stops. 4. You then read the value of the control on the dynamic VI via Get Control Value. The problem is that after #2, you may not have anything in place to make sure #3 happens before #4. It could happen the other way around, depending on the whims of the thread scheduling system. QUOTE I also have "Read n" and "Read t" methods that captures n data packets and captures packets for t time respectively. These would benefit from the notifier I think. If you're retrieving N data points, rather than just one, you could also look into using a queue instead of a notifier. A notifier handles one element, a queue handles many. QUOTE For this to work wouldn't I need to have a separate loop in the main vi dedicated to waiting for the notifier? Depends on exactly how you do it. The Wait on Notification node blocks until it receives a notification or (optionally) until it times out. You can also use the Preview Notifier node to check to see if a notification has been sent yet. QUOTE Since my implementation is in a class, I don't have a main vi in my class to monitor the notification from the dynamic vi. That's exactly what the Wait on Notification node does: monitors a notification. QUOTE Isn't this resolved by putting the indicator in the data collection loop where it is continuously updated? True. You could continuously keep the control in the dynamic VI up-to-date and grab its value using the Get Control Value method. That may have a significant speed impact. Property nodes run in the UI thread, so they are slow. I'm not sure if Invoke nodes run the same way. Note that you'll also have to manually convert the output from a variant to the correct data type. Notifiers and queues know the correct data type and do that for you. Again, you'll have to beware race conditions to make sure your dynamic VI is in the state that you think it's in. Quote Link to comment
smenjoulet Posted July 24, 2008 Report Share Posted July 24, 2008 As normandinf mentioned, User Events will work well for you here. I've attached a simple example based off a technique we've been using sucessfully for a few years. It is the LVx technique mentioned by Norm Kirchner above but without Object Orientation. The concept is this: 1) Your main VI ("Test.vi" in my example) registers an event by running a VI (in this case "Export Test.vi") that creates a user event on the first call. The data type of the event can be whatever you choose (numeric, string, variant, etc.) 2) The main VI calls the dynamic VI (Dynamic.vi in my example). I like to use a Static VI ref for this, but it doesn't really matter. 3) The dynamic VI runs and generates its data. Upon completion it calls "Export Test.vi", which on subsequent calls generates the previously registered user event. It passes the data it generated through the user event. 4) The user event fires in the main VI and gets the data from the user event. You then operate on the data in whichever way you choose. 5) Wash, rinse, repeat 2-4 as needed. To try it out just extract the zip and open/run "Test.vi". This is a basic example that can be very powerful and extended in any number of ways (i.e. wrapping it with OO like Norm has worked on). Hopefully, this will help you get started. If not, I still needed a 10th post. Regards, Scott Menjoulet Quote Link to comment
Daklu Posted July 25, 2008 Author Report Share Posted July 25, 2008 Thanks for coming out of the shadows to share that Scott. (Keep up that awesome posting rate! You'll hit 1000 sometime in 2408! ) I did figure out how to use Norm's demo but the sheer number of vis left me puzzling over exactly how it is working and how to implement it. I think that's the route I'm going to try first. As a bonus your demo will help me understand Norm's better. Couple questions: Is there any particular reason you create the user event and generate it in the same vi? Since I am implementing this in a class is there anything preventing me from exposing a public Register Event vi and have a private Generate Event vi? Rather than have Main.vi register for the event at program start, I need to have the ability to Register and Unregister at runtime. Are there any gotchas if I were to implement it this way? QUOTE 2. You run Stop to tell the separate thread (the dynamic VI) to stop running. How does the dynamic VI know when to stop?My Stop vi wraps a functional global and sets it to TRUE. The dynamic vi checks the functional global after every iteration. I think doing it this way will help avoid a race, but I can see how I may drop a data point or two at the end.QUOTE That's exactly what the Wait on Notification node does: monitors a notification.Yes, but somebody still has to monitor the notification to see when it occurs. So wouldn't I either have to check for the notification with every iteration of my main processing loop or have a separate loop dedicated to checking the notifier? Note the dynamic vi will be started and stopped several times during a test and Main.vi needs to continue running in parallel to the data collection.(Although I am looking at user events as my primary path I'm still learning a lot from the notification discussion.) Quote Link to comment
LAVA 1.0 Content Posted July 25, 2008 Report Share Posted July 25, 2008 I have been using a method similar to the notification illustrated above but I am using three that get created prior to setting the FP controls on the dynamic VI. One que just let the invocation cod eknow the VI is up and running (dynamic queues up status including error code from start-up) Second and third third pass method request and the result. The caller is structured as an AE that tracks the queues and provide a by-reference access to the instaciated active objects. Ben Quote Link to comment
eaolson Posted July 25, 2008 Report Share Posted July 25, 2008 QUOTE (Daklu @ Jul 24 2008, 08:39 AM) Yes, but somebody still has to monitor the notification to see when it occurs. So wouldn't I either have to check for the notification with every iteration of my main processing loop or have a separate loop dedicated to checking the notifier? Note the dynamic vi will be started and stopped several times during a test and Main.vi needs to continue running in parallel to the data collection. Yes, either you'll have to have something use Preview Notifier and poll every so often, or have a separate thread/loop with a WON node. Depending on what you're doing with the data, the event method may be a good way to go. I know it's generally considered bad form (and can be problematic) to have more than one Event Structure. Is that still the case if you segregate one event structure handling UI events and another handling data-driven user events? Depending on what you do with the data and what your data collection rate is, I wonder if mixing the two could lead to the front panel seeming sluggish. Quote Link to comment
smenjoulet Posted July 25, 2008 Report Share Posted July 25, 2008 QUOTE Thanks for coming out of the shadows to share that Scott. (Keep up that awesome posting rate! You'll hit 1000 sometime in 2408! ) Post #11. I better slow down or I'll hit 1000 by 2399! QUOTE (Daklu @ Jul 24 2008, 08:39 AM) Couple questions: Is there any particular reason you create the user event and generate it in the same vi? Since I am implementing this in a class is there anything preventing me from exposing a public Register Event vi and have a private Generate Event vi? Rather than have Main.vi register for the event at program start, I need to have the ability to Register and Unregister at runtime. Are there any gotchas if I were to implement it this way? To me it provides some simplification, compactness and a kind of encapsulation. I don't see why you couldn't have two distinct methods, one public and one private. The only gothca if not registering at start (before your dynamic VI has any chance to run) is to make sure the event is registered first. You are essentially creating an API for your VI, application, exe,... What we do is create GUIs for device communication. These are LabVIEW built exe's. The exe has these exported VI's (API) as we call them and we can automate the GUI operation from the LabVIEW IDE, TestStand, another LabVIEW exe, etc. It's kind of like a pure G based ActiveX. It's not strictly just for communication/data passing/synchronization within the development environment or one built exe. It can span across multiples of these. So it provides a common interface for a user to debug a device using the GUI manually, but also to automate testing of the device after the debug cycle is complete (or even as part of the debug work). I'm always looking to improve it (Norm's OO wrapping is one avenue), so comments & suggestions are always welcome. Scott Quote Link to comment
Yair Posted July 25, 2008 Report Share Posted July 25, 2008 QUOTE (eaolson @ Jul 24 2008, 05:28 PM) I know it's generally considered bad form (and can be problematic) to have more than one Event Structure. Is that still the case if you segregate one event structure handling UI events and another handling data-driven user events? There's no inherent problem with having two event structures. The problems come if you have two in the same loop (bad, since they can block) or when you handle filter events in more than one without knowing how they work or when you use the same dynamic event registration refnum in both structures, etc. Quote Link to comment
eaolson Posted July 25, 2008 Report Share Posted July 25, 2008 QUOTE (Yair @ Jul 24 2008, 12:00 PM) There's no inherent problem with having two event structures. Inherent problem, no. But I have seen people saying basically that it's bad style. QUOTE The problems come if you have two in the same loop (bad, since they can block) or when you handle filter events in more than one without knowing how they work or when you use the same dynamic event registration refnum in both structures, etc. I don't use dynamic events a whole lot, so I wasn't aware of that last issue (or had forgotten about it) until just now. It's just obscure enough, and kind of buried in the Help, that I think it warrants repeating: Each event structure must have it's own Register For Events node. Craig S. explains why here. Quote Link to comment
Daklu Posted July 26, 2008 Author Report Share Posted July 26, 2008 Thanks to everyone's help, I have an example "Timer" implementation that does most of what I want it to do. I can't read data from the dynamic vi until it stops running, but that's okay. I can start/stop the timer and register/unregister for the event independently. I haven't quite wrapped my brain around the difference between an Event Registration Refnum and User Event Refnum, other than the User Event Refnum can carry data with it. Is the idea that an event structure can have only a single Registration Refnum associated with it, but each Registration Refnum can have multiple User Events? In other words, the Reg Ref defines which event structure handles the event while the User Ref defines the event that occurred? The other thing that concerns me is that I don't use the Unregister For Events or Destroy User Event prims at all, primarily because I haven't figured out where to put them yet. I think repeatedly hitting the Register button will create a memory lake. I'll have to play around with that a bit more. Quote Link to comment
Yair Posted July 26, 2008 Report Share Posted July 26, 2008 QUOTE (eaolson @ Jul 24 2008, 11:42 PM) Inherent problem, no. But I have seen people saying basically that it's bad style. Like any tool, they have advantages, disadvantages, dangers, etc. There are places where it's the best solution and places where it's a terrible solution. If you know the details, you can use it. If not, you can not use it or use it and risk running into trouble. The thread you linked to is my thread, so you can see I was in the last group in that case. :headbang: QUOTE (Daklu @ Jul 25 2008, 01:41 AM) Thanks to everyone's help, I have an example "Timer" implementation that does most of what I want it to do. I can't read data from the dynamic vi until it stops running, but that's okay. As I said, I'm not a fan of this approach. I would prefer using a notifier or sending the event refnum to the dynamic VI and having it throw the event. QUOTE Is the idea that an event structure can have only a single Registration Refnum associated with it, but each Registration Refnum can have multiple User Events? Essentially, yes. Each event structure should have a single RR which can have multiple events (both dynamic and user) registered. The actual list of events has to be static, but each event can be registered and unregistered dynamically. QUOTE The other thing that concerns me is that I don't use the Unregister For Events or Destroy User Event prims at all Be sure to use them. Not using them is a recipe for having your program get stuck (or at least it used to be) and probably having memory leaks as well. Quote Link to comment
Daklu Posted July 27, 2008 Author Report Share Posted July 27, 2008 QUOTE (Yair @ Jul 25 2008, 02:48 AM) As I said, I'm not a fan of this approach. I would prefer using a notifier or sending the event refnum to the dynamic VI and having it throw the event. You didn't specify whether you meant the User Event Refnum or the Event Registration Refnum, so I'll assume you meant the User Event, since I do pass the Registration Refnum to the dynamic vi. If you did mean the Registration Refnum, then... we agree! Why have the main vi pass the event refnum to the dynamic vi? The main vi isn't concerned about the event refnum, only that the event will (or will not) fire and that the correct event structure (if there are more than one) is handling it. This can all be handled with the registration refnum. Forcing the main vi to unnecessarily handle the user refnum just creates more bookkeeping for it. Is it just a personal preference or am I missing something technical? Quote Link to comment
Yair Posted July 27, 2008 Report Share Posted July 27, 2008 QUOTE (Daklu @ Jul 26 2008, 04:13 AM) I'll assume you meant the User Event Yes, I did, but I meant that you should pass the event refnum to the dynamic VI and then throw the event from there instead of reading the control value from the dynamic VI. That way, the code will be more robust and you can trigger the event at the same time in every event structure which registered for it. I hope this makes it clearer. If not, you should look at LVx. I can't look at it currently, but it probably does something similar. If this still isn't clear, ask again and I'll try to post an example. Quote Link to comment
Norm Kirchner Posted July 29, 2008 Report Share Posted July 29, 2008 Daklu, Perhaps this might make things more clear on how the flow is supposed to go between the dynamic and main VI Quote Link to comment
Daklu Posted July 29, 2008 Author Report Share Posted July 29, 2008 I understand now. The benefit to passing the UsrEventRef to the dynamic vi is that it can carry the data back out to the main vi instead of having to do weird things like getting references to controls. (Sometimes it takes a while for good ideas to penetrate my thick skull...) Purely hypothetical question... If I didn't need any data from the dynamic vi would there still be reason to pass the UsrEventRef to the dynamic vi? Or would it make sense to simplify the main vi by containing the UsrEventRef entirely in the dynamic vi and passing in the EventRegRef instead? Quote Link to comment
Norm Kirchner Posted July 29, 2008 Report Share Posted July 29, 2008 You keep talking about passing the Event Reg Ref... and I'm surprised no one has mentioned this yet but you can not pass that reference around. The proper usage of it is to be used within the same chain of VI's as in same VI as event structure or maybe passed out of a subVI for simplicity purposes only to be passed to the calling VI but never to a dynamically called VI. If you really wanted to do bare bones on this w/ no events. All you would use is an occurance (IMHO) Pass the occurance to the dynamic VI and wait on it in the main vi. Thats it. 1 Quote Link to comment
Michael Aivaliotis Posted July 30, 2008 Report Share Posted July 30, 2008 QUOTE (Norm Kirchner @ Jul 28 2008, 11:24 AM) You keep talking about passing the Event Reg Ref... Ditto on that. You should pass the User Event Refnum. Then just register your events at the event structure. You can have multiple event structures registered for the same event. Also, you don't really need to "pass" it. You can just as easily use a functional global that stores the User Event Refnum(s). 1 Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.