04-21-2011 05:18 PM
Multiple instances of the web method isn't the issue; the issue is application instances. For example, in the development environment, each project is a separate application instance, and you cannot share refnums between them. Similarly, each compiled application is a separate application instance, so you can't share refnums between compiled applications. The web server is also a separate application instance, in which web method VIs execute, so web method VIs can't share refnums with VIs running in another application instance.
I have no experience with shared variables so I don't know what options are available there and I can't tell exactly what you're doing from your screenshot. Are all the VIs that will handle the event running inside your main application, and you need the web method to trigger them?
What I was trying to say about VI server, perhaps too succinctly, is that you can create a subVI in your main application instance that exists only to trigger an event. Store the user event refnum in a shift register in that subVI. Make that subVI accessible to VI server. In the web method, use VI server to call the event trigger subVI inside the main application instance. There's a limited discussion of this approach here; the user there had queues instead of user events but the idea is the same.
You should be able to send a user event refnum over a shared variable within a single application instance, although I don't know why you would ever do that instead of using a wire or a functional global variable - just typecast the refnum to a U32 (and be very careful that you typecast it back to exactly the same type).
04-21-2011 05:23 PM - edited 04-21-2011 05:25 PM
Thanks for the details.
I get the part about application instances. But I'm not trying to pass the refnum between a web service and a local VI--I can do that fine with network-published SV's. The problem comes when the web service tries to open multiple instances and requires a single refnum. All this happens within the deployed web service and is contained within one application instance, I believe. So it really is about multiple web method instnaces. Am I seeing this all wrong? Is not the entire web service an application instance?
I don't have any experience with VI servers so I'll have to look at that in more detail. The link looks promising, thanks.
04-21-2011 05:49 PM
@pltrogon wrote:
I get the part about application instances. But I'm not trying to pass the refnum between a web service and a local VI--I can do that fine with network-published SV's. The problem comes when the web service tries to open multiple instances and requires a single refnum. All this happens within the deployed web service and is contained within one application instance, I believe. So it really is about multiple web method instnaces. Am I seeing this all wrong? Is not the entire web service an application instance?
Without seeing your code it's hard to be certain that I understand what you're trying to do. Are you building a compiled application that includes web services? If so, you actually have two application instances - one for the VIs that run when you launch the application, and a separate one for the web method VIs. You cannot share an event refnum between them, so a web method cannot directly trigger an event in the main application instance. If that's not what's happening, then I need more clarification to understand your situation.
04-21-2011 06:00 PM
OK, here goes:
The web service VI's interact with the SVs. They don't know anything about where the values came from; it could be a seperate application instance running in parallel on the same machine, a VI in a different machine, or even manual clicks in the DSM. So in practice there may be [and will be] two application instances but one of them is irrelevent. For debugging purposes I'm typically using the DSM to manually change SV values.
So I'm building and deploying a web service that contains two VI's: one is an auxiliary VI that runs immediately upon deployment. The other VI is a web method VI that runs whenever asked to by a web user. It cannot be wired to the aux vi so it needs to use globals or SVs. The web method VI waits for a SV value change event [from DSM or another application instance] before sending out data [to avoid polling]. Since I want each web method instance to respond to each event, I need each web method instance to register for events using the same notification refnum. The notification refnum could be generated in the AUX VI and passed to the web method VI's through SV's.
I have an urge to draw a picture right now...
Your suggestion about casting the refnums as U32s worked great, at least as far as preventing the SV from crashing [why does passing a refnum as a variant into a SV kill it? Not that important but odd]. I still can't get the web method VI's to trigger on events using notification refnums from a parallel VI without using wires, though...
04-21-2011 06:47 PM
OK, rereading your post I think I understand where we're crossing wires. This is what I think you're saying:
Web method VI's and their associated auxiliary VIs exist in separate application instances.
If this is true then off to polling I go!
04-21-2011 06:47 PM
As I mentioned I don't have any experience with shared variables, but any reason why each web method VI can't register for a shared variable value change each time it runs? I'd think that multiple VIs can register for the same value change event, and that might be easier than passing around the event refnum.
Instead of putting the user event refnum in a shared variable, why not put it in a functional global variable?
Moving away from shared variables for a moment, say you do something similar with a user event, but you create one web method that triggers (rather than waits on) the user event. Do you get an error from Generate User Event? Have you tried using a notifier instead of an event? Multiple VIs can all wait on the same notifier, and then you'd have an error out terminal which would indicate if the notifier refnum is invalid. As an added benefit, you can refer to notifiers by name, eliminating the shared variable.
04-21-2011 06:58 PM
@pltrogon wrote:
OK, rereading your post I think I understand where we're crossing wires. This is what I think you're saying:
Web method VI's and their associated auxiliary VIs exist in separate application instances.
If this is true then off to polling I go!
I'm personally still unclear on the definition of an auxiliary VI, but that was not what I was trying to say. As far as I can tell, the point of an auxiliary VI is that it isn't a web method but does execute in the same application instance. However, I haven't been able to find any useful documentation clarifying this.
There is a separate application instance for VIs that you build into an application that you then launch in order to make sure the LabVIEW web server is up and running in order to serve your web service, as described in the process for creating and building an application containing web services. However, I don't think that applies to auxiliary VIs.
04-21-2011 06:59 PM
My original implementation did just that; I registered for the relevant SV events in each web method instance. The issue was that one event was picked up by a single web method instance, meaning that only one user would see new data coming in. The only way to register for events that allowed more than one parallel process to trigger on the same event required forking the notification refnum. Thus all this garbage.
I've tested the functional global as well... the issue seems to be exactly what you have stated. If I have two VI's [web service or no] without codependencies then I can't share refnums between them, even if they're running at the same time, in the same project, etc.
Can you explain this a bit more? "say you... create one web method that triggers (rather than waits on) the user event. Do you get an error from Generate User Event?" I'm triggering on user events just fine... but the trigger source needs to come from another VI, not inside the web service.
I've pondered using notifiers but I've run into the same issue. I can't use notifiers across application instances.
04-21-2011 07:17 PM
Here's where I get confused about what you're trying to do. Where do you create the event refnum? In the aux VI (which should be running in the web service instance), or somewhere else? It should be fine if you're sharing it between the aux VI and the web method VI. Anywhere else and you've crossed the boundary into another instance and you'll need some other approach.
Have you debugged this at all within the LabVIEW environment? You can stop web method VIs, run them with execution highlighting, etc - all the normal tricks. You might need to hit the pause button in the toolbar so it will pause before it actually executes. If you do this with a functional global variable you should be able to see if it's storing data between instances as you expect.
Do you have any continuously-running VI that maintains the event refnum? If not, it's possible that when everything goes idle, the refnum is being destroyed, and then when you next launch a web method VI the refnum is no longer valid.
@pltrogon wrote:
Can you explain this a bit more? "say you... create one web method that triggers (rather than waits on) the user event. Do you get an error from Generate User Event?" I'm triggering on user events just fine... but the trigger source needs to come from another VI, not inside the web service.
I've pondered using notifiers but I've run into the same issue. I can't use notifiers across application instances.
If you know that notifiers won't work, then event refnums won't either. I'm still not clear where you're creating the event refnum, but I was thinking that ignoring the shared variables, you could create a user event (preferably in the same place as you create the shared variable event) and then share that with the web method VIs. If one of those web method VIs sets the event, rather than waiting for it, then you could easily see if it's receiving a valid event refnum by looking at the error out terminal. Part of my confusion may be that you're "triggering" on two different things: first your external source causes the shared variable value to change, and that in turn sets a LabVIEW event to which your web method VIs are expected to react.
04-21-2011 07:33 PM
Here's a thought experiment that uncovers where the weakness in my understanding:
Take two VI's, call them VI1 and VI2. Neither calls the other; there are no wires connecting them. VI1 writes to a global, VI2 reads from the global. Are the VI's in the same application instance?
If the answer is yes, then the global could contain a refnum. If not, the refnum would not be valid.
My [poor] understanding is that the very fact that these two VIs run independently and have no dependency means that they are separate application instances. This implies that aux VI's and web method VI's can't be in the same application instance because by their nature they have no explicit dependencies. I'm very likely to be wrong here but this is my thinking.