Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with Linked Network Actor (based on the supplied example)

Solved!
Go to solution

I'm trying to use the Linked Network Actor (LNA) library (an extension to the Actor Framework) to send messageegs between actors in two seperate applications, just like the normal Actor Framework sends messages between actors within one application.

I've downloaded https://decibel.ni.com/content/docs/DOC-24051 which comes with a small example which launches two network actors in a single main VI (see attached example.jpg). I've tried to replicate this example but with the two network actors in two seperate main VIs.

In my example I made two actors ActorA and ActorB and launched two LNAs Anet and Bnet in their actor cores. ActorA and ActorB are launched from mainA.vi and mainB.vi. The actor cores of ActorA and ActorB have an event structure for starting the LNA, connecting to the other actor's LNA and sending messages. Furthermore, the actor cores have a while loop where messages are dequeued and the class name of the message is read and acted upon (see the bottom loop in "ActorA Actor core.jpg"), this loop is pretty much a copy of the one from the LNA example that came with the library.

My problem is that I don't really know if this is the proper way to test whether or not the network actors work (by this I mean the dequeuing loop), and if it is the proper way, then I am pretty sure I messed up with handling the enqueuers and dequeuers (giving the correct ones to the LNAs etc.)

Taking ActorA's actor core as an example:

ActorA's LNA is called Anet and is launched with the enqueuer coming from calling "Read selfenqueuer" on "ActorA in". The "Caller-to-Actor-Enqueuer" output of the Launch Actor.vi is then used with a shift register to provide the enqueuer for the Connect and Send cases.

In the other half of the actor core, the reference to the toplevel actor's message queue is obtained and its dequeuer is read. Messages are then dequeued and acted upon with a case + event structure.

I am almost positive that the enqueuers are messed up in the project i attached to this post (Network actor test.rar), but I've tried a lot of different things and decided it was better to ask then get even more confused and mess more things up.

So to sum this up: Am I on the right track when it comes to launching, connecting and sending messages with the LNAs and simply messed up something with the enqueuers, or have I fundamentally misunderstood how the LNAs should be utilized?

By the way I am aware that the front panels and perhaps the block diagrams are a bit messy and that the stop cases are not working properly.

0 Kudos
Message 1 of 5
(5,735 Views)

In the other half of the actor core, the reference to the toplevel actor's message queue is obtained and its dequeuer is read. Messages are then dequeued and acted upon with a case + event structure.

Not according to your image, where a separate message queue is created (with no enqueuer created so no messages can ever be sent).

Message 2 of 5
(3,138 Views)

That was my initial thought as well (and now you confirmed it), but I got kind of confused and decided that this might work after reading the context help for Obtain Message Queue, i.e. "Obtains the reference to the message queue that the caller uses to communicate with the top-level actor". But I have misunderstood what they are referring to with regards to "reference".

Prior to this (the current version of the code) I had that similar loop in my mainA.vi since I obtain a message queue to pass to ActorA in that vi. I never got that to work, but it seems like the more sensible solution I guess. I'll try it again and return with some new screenshots, but if you have any other comments/suggestions feel free to post them.

0 Kudos
Message 3 of 5
(3,138 Views)

So I tried something I had thought about for a while.

In mainA.vi and mainB.vi I obtain the actual dequeuer reference and bundle it with ActorA and ActorBs private data (which is just a message dequeuer.lvclass).

In the actor cores for ActorA and ActorB I then unbundle the message dequeuers and use these in the "dequeue loop" in the bottom of the block diagram.

However, this still doesn't seem to work. None of my indicators are updating (least of all the while loop indicator in the dequeue loop) which means that there are never getting anything dequeued. This could be because there is nothing to dequeue (maybe I am using the wrong enqueuer for connect/send etc?) or because I am trying to dequeue from another queue than the one I enqueued on.

Here are some new screenshots and the project. Any help is much appreciated.

ActorB Actor Core.jpg

mainB.jpg

Not sure how to attach a zip file to a reply, so instead I'll edit my original post to include the new project.

0 Kudos
Message 4 of 5
(3,138 Views)
Solution
Accepted by topic author Kaspercj

As you suspected, your approach is not going to work.

The example that ships with the LNA is a test harness that demonstrates how this actor operates.  It does not show how to use the LNA as a nested actor, which is what you're trying to do.  Since you're supposed to nest the LNA, maybe I'll make a better example for the next release.

When your caller is not an actor (like the test harness in this case), it has to explicitely provide a queue and message handling loop.  You get these things for free if your caller is an actor; trying to provide them yourself is where you went wrong.  Lets look at your most recent two diagrams.

ActorB's attribute, Message Enqueuer in B, should not exist.  You should not pass it in from MainB.  First off, you're already doing that - this enqueuer is the same enqueuer you are passing to ActorB through Launch Actor.vi.  This is the same enqueuer you get from ActorB when you invoke Read Caller Enqueuer.vi.  Delete the attribute from ActorB's ctl, and delete the accessor.  Delete the broken wire on MainB.

In ActorB's Actor Core.vi, delete the bottom loop in its entirety (the one that uses Message Enqueuer in B).  Delete the bad unbundler as well.  Everything else on this diagram is OK (at least from what I can see in the JPG).

Now, look at the other cases in the event structure.  You should have several that send messages (I assume the same set that is used in the example).  All of those messages are abstract messages.  When you send them to an actor, you will need to make child classes of these messages that implement a Do.vi.  In that Do.vi, you will call the method of the receiving actor that will use the data of the message you sent.  So, for example, if you want the receiving actor to respond to a Loopback message, you will make a child of Loopback, create a Do.vi for it, and call a method of the receiving actor that will (for example) display the time stamp on the front panel of the receiver.  Your sender should send the child message, not the abstract parent.

If that's confusing to you, just make messages for your actors A and B like you always do.  From the actor cor of A, send B messages to B, and vice versa.

Make the same changes to the Actor A set that you made to B (making sure you send the right messages) and you should be good to go.

The example Actor Framework on CompactRIO (and Other RT Targets) usese the LNA to move messages between a host and an RT target.  Take a look at that example, and you'll see what I'm talking about here.

0 Kudos
Message 5 of 5
(3,138 Views)