Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

How does AF handle continuous execution of some action?

Solved!
Go to solution

As per title, if some Do.vi is supposed to be a continuous process which is started on request and stopped on request, how does the AF handle this?

By my eyeballing so far, all I've seen is that you could do it by having the process enqueue itself to the actor, but this seems really ugly to me (similar to Daklu's aversion to the QSM which enqueues to itself).

Thanks for the help.

Message 1 of 34
(19,346 Views)
Solution
Accepted by topic author GotRobotFriends

In general, you don't want the method called by 'Do' to be a continuous process.  You want it to be a message, perhaps something that starts a continuous process. 

A continous process is IMHO best implemented as a parallel loop the message handler (ie: Actor.lvclass's Actor Core.vi).  In order to create a parallel loop, you'll want to override actor core.vi for the specific actor class and create a loop that is parallel to the call of the parent's actor core.  Typically, you'll want to store some message communication mechanism (ie: a user event or queue) in the private data of that Actor to enable direct communication between the message handling loop and the parallel process that is continuously executing.

Hopefully this block diagram illustrates my point.Parallel Loops.png

Elijah Kerry
NI Director, Software Community
0 Kudos
Message 2 of 34
(5,137 Views)

Of course, this parallel process is handling UI events, but it could just as easily be a continuously running DAQ task, etc... Note that in this example, the UI event handler has the queue to send messages to the message handler, and a user event is stored in the class data, allowing methods that are invoked by Do.vi to pass a command back the other way.

Elijah Kerry
NI Director, Software Community
Message 3 of 34
(5,137 Views)

Thanks Elijah,

That gels nicely with how I've been building sub-processes in my current framework. For some reason, I was locked into the idea that each Actor Core should only have one while loop on its block diagram.

0 Kudos
Message 4 of 34
(5,137 Views)

Actor.lvclass:Actor Core.vi just handles communication between Actors. The concrete Actor's various methods (including its override of Actor Core.vi) are responsible for the behaviors of that actor.

0 Kudos
Message 5 of 34
(5,137 Views)

Further to my previous question, how does one best handle state changes of the parallel loop. For example, I want my continuous process to be in one of three states, Idle, Read Position, and Control on Position. I went on my merry way including a state Enum in my actor's private data, then brain-froze when it came to how to actually get that state out of the actor data and into the parallel loop? It doesn't make sense to branch the object into the parallel loop, then I'm just reading the inital state of object. In my previous architecture, I would do it via a local variable which is updated in the QMH loop and read in the parallel loop.


Stumped.

0 Kudos
Message 6 of 34
(5,137 Views)

... how to actually get that state out of the actor data and into the parallel loop? It doesn't make sense to branch the object into the parallel loop, then I'm just reading the inital state of object. In my previous architecture, I would do it via a local variable which is updated in the QMH loop and read in the parallel loop.

I generally just use a single element queue to store variables (e.g. your state) which need to be passed to the parallel loop. I keep the queue ref in my class private data, so then it makes perfect sense to branch the wire into the parallel loop and use an accessor to get the current value.

Chris

0 Kudos
Message 7 of 34
(5,137 Views)

Sounds like black magic to me, I was lead to believe that branching the class wire creates another instance of the object, in which case, your accessor (if it's working inside the loop) would just be giving you the default value in your SEQ. This must not be the case as it sounds like it's working for you, so what is going on under the hood here?

The only way that makes intuitive sense to me at the moment, building on your idea, is that the SEQ is initialised and then its reference (rather than the actor object wire) is passed to the parallel loop where it is checked in a zero timeout fashion?


Edit: Ohhhhhh, because your SEQ reference never changes, you can put the accessor inside the loop, but it seems kind of pointless if you can just put the post-initialisation accessor outside the loop and pass in the SEQ reference.

0 Kudos
Message 8 of 34
(5,137 Views)

I was lead to believe that branching the class wire creates another instance of the object, in which case, your accessor would just be giving you the default value in your SEQ.

Branching the class wire copies the class private data, but you will almost certainly need to do this from time to time. See ElijahK's block diagram above, for example.

In my case I create the single-element queue pretty early in the workflow (i.e. before any branching, and before the "call parent" of actor core), so my accessor just gives me a nicely initialised queue ref wherever I need it.

Magic, but no frog spleens and bat wings required...

0 Kudos
Message 9 of 34
(5,137 Views)

Edit: Ohhhhhh, because your SEQ reference never changes, you can put the accessor inside the loop, but it seems kind of pointless if you can just put the post-initialisation accessor outside the loop and pass in the SEQ reference.

Yep, whichever works for you. Depends on whether you have more than one accessor, etc... But you still need to branch! 🙂

0 Kudos
Message 10 of 34
(5,137 Views)