Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Asynchronous Call Within a Do.vi?

This may be a dangerous thing, but I am not sure what the best solution is and would like some feedback.

I have an actor that is collecting data from the DAQ and it will also handle some scaling of the collected data. I do not want the scaling method to hold up acquiring data, so I would like to do this asynchronously. My first thought was to just create an actor that does nothing but scale the data from the DAQ; however, I didn't really want to have to duplicate the scale and offset values or separate them from the DAQ private data. The DAQ actor has all the channel information as well as scaling stored in its private data. My solution is to call a Process Data vi asynchronously in it's Do message:

Asynchronous DO.PNG

This will be called around 10x a second, but the amount of data is pretty light and should be around 160kB per call. There is a potential for several of these "Process Data" vi's to be running at once as they work through a data backlog. I am hoping that there won't be an ever increasing number of these running causing severe memory leaks.

I diagrammed this thought out:

DAQio.png

Looking at this now, it seems that there should be two separate actors. Should the Process Data be a child of DAQio so that it hass access to the scaling information? This is probably a basic architecture question, but I am pretty stuck and need a shove in the right direction.

The project is attached, it is a work in progress. Please be gentle. 😉

Thanks,

Drew

0 Kudos
Message 1 of 4
(4,785 Views)

Unless you've already tried it and found a problem, yes, I would say this seems like a prime case for a nested actor. Parallel loops within Actor Core are the poor man's version of the nested actor. They behave pretty much exactly like the async process that your considering creating --- you give them all the values and they execute. The parallel loop and the real actor are generally a lot easier to stop if you need them to abort at some point.

> however, I didn't really want to have to duplicate the scale and

> offset values or separate them from the DAQ private data.

Not sure why duplication of these values is a downside. In your proposed solution, you're making a copy of the entire DAQ actor. Why would copying a subset of that bother you? Tangent: Anytime you find yourself copying the entire actor, there's almost certainly something wrong in your design that will be a problem in future refactorings and/or debugging. That's a pretty solid guideline that I have yet to see not be true. In your case, you're giving your scaling function access to far more data than it needs, making it more dependent on the internal structure of your DAQ actor than it would otherwise be.

You have them in the DAQ actor and you would send a message to the scaling actor so it has a copy. If those values change, it's the DAQ actor's job to send a message to update the nested actor -- a message that it sends at the same time it receives the new values message itself.

Message 2 of 4
(3,677 Views)

First thing to ask is “are you sure you need this?”  Many DAQs run continuously, buffering data asynchronously to the collecting program, so it doesn’t matter if the program is sometimes busy processing data.  Don’t reinvent the wheel.

Second, one has to be careful with asynchronously calling VIs.  The Open Ref in your code will have considerable overhead and also has a major problem: if the User opens a menu on the Front Panel it will block waiting for the menu to be closed (this issue has something to do with LabVIEW’s “root loop”, whatever that is).  One can get around these issues (and you can look in the AF’s “launch actor” method to see how it can be done) but you have to ask if it is worth the complexity.  I actually made an “Asynchronous Action” parent class to hide the complexity and make things like this easy, but it isn’t intended to work with the AF, unfortunately.  I think a simpler way is to use dedicated “worker loops” in your actor.  These are poor man’s nested actors, when you really want an actor, but nested actors are overly complex and restrictive when you really need a dedicated, specialized worker loop.

Message 3 of 4
(3,677 Views)

Thanks for the responses, and you both have given me a lot to think about.

One path I had looked at is creating a queue and paralel loop for the DAQ task to stream data to; however, using a nested actor does make sense also, being that it is essentially a queued while loop. Again, this could be done with a dedicated paralel processing loop in the DAQ actor, but as AQ points out, any changes in the scaling factors would have to be sent to that loop. Plus, the added bonus of possibly complicating shutting down the paralel loop within the actor core.

The duplication of the actor data is something that I always miss. I was thinking more about getting the data and scalars to a method within the actor's class, and still allowing the DAQ task to continue to operate with out risking timeout errors or loosing any data.

I have created nested actors before and had pretty good success with them. I may shift gears away from the DAQ interface for a couple of days to mull this over and start working from the top down on the other end of the application. I post where I ended up here.

0 Kudos
Message 4 of 4
(3,677 Views)