LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Actor framework - message communication problem

Hello everybody,

 

i have some strange issue using actor framework, perhaps you can give me some guidelines.

 

Creating application which has only two actors, one is GUI and another is LIN bus communication.

 

From GUI i send list of LIN frames which need to be send to LIN actor which is then sent to bus.

In LIN actor there is helper loop, which then go throw the list constantly and write to the bus.

And this works just fine.

 

But what happened next, i cannot see where is the problem.

1. send list from gui to lin, running constantly

2. send new list to overwrite old list 

3. then imediatelly send old list again.

 

In this process, i don't have new list on bus.

It seams that new list never go to the bus, because old list from 3. step, overwrite list from step 2, before new list is executed.

Is it even possible?

I thought that actor keep buffer in background, and executes everything?

 

Sorry i cannot share my project.

 

Thanks.

0 Kudos
Message 1 of 14
(1,623 Views)

The Actor Framework buffers all messages and does not change the order of elements with the same priority. Maybe the messages are executed before the helper loop getsa chance to process the new data? That would be the case if the actual sending of data happens in the timeout case of a dequeue or event structure. Hard to answer without knowing more details

 

Tangentially, you might not actually need the helper loop. The message that receives new data can immediately send it on the bus. Sending the data would be its own sub VI, that calls itself by actor message.You need some more logic that you don't pile up those messages, but that would allow you to get rid of the helper loop while keeping the actor responsive. If you have a wait time between sending data on the line then keep the helper loop.

0 Kudos
Message 2 of 14
(1,590 Views)

@milan87 wrote:

Hello everybody,

 

i have some strange issue using actor framework, perhaps you can give me some guidelines.

 

Creating application which has only two actors, one is GUI and another is LIN bus communication.

 

From GUI i send list of LIN frames which need to be send to LIN actor which is then sent to bus.

In LIN actor there is helper loop, which then go throw the list constantly and write to the bus.

And this works just fine.

 

But what happened next, i cannot see where is the problem.

1. send list from gui to lin, running constantly

2. send new list to overwrite old list 

3. then imediatelly send old list again.

 

In this process, i don't have new list on bus.

It seams that new list never go to the bus, because old list from 3. step, overwrite list from step 2, before new list is executed.

Is it even possible?

I thought that actor keep buffer in background, and executes everything?

 

Sorry i cannot share my project.

 

Thanks.


Hello, 

 

Without seeing the code, I think your issue may be in the helper loop. In a very broad sense, it is not good to use while loops in the actor framework. The reasoning is that as long as you are executing in a while loop on your actors 'class instance' you will never dequeue another message for that actor. You can think of the execution of all code on an actor instance as a thread, if you never release the thread the underlying actor messaging system (for a single actor) can never execute. 

 

A much better solution to using a while loop is to simply use the actor method to call itself ( by sending a call message to itself) based on some logic, this will create a while loop in the context of the actor instance and allow for you to dequeue the other messages between runs of the 'while loop'. 

______________________________________________________________
Have a pleasant day and be sure to learn Python for success and prosperity.
0 Kudos
Message 3 of 14
(1,581 Views)

@Jay14159265 wrote:

In a very broad sense, it is not good to use while loops in the actor framework. The reasoning is that as long as you are executing in a while loop on your actors 'class instance' you will never dequeue another message for that actor. You can think of the execution of all code on an actor instance as a thread, if you never release the thread the underlying actor messaging system (for a single actor) can never execute. 

 

A much better solution to using a while loop is to simply use the actor method to call itself ( by sending a call message to itself) based on some logic, this will create a while loop in the context of the actor instance and allow for you to dequeue the other messages between runs of the 'while loop'. 


I disagree. I've got helper loops in nearly all of my Actors and they work just fine. A helper loop runs in parallel to Actor Core. It doesn't matter what the helper loop is doing, the Actor still processes messages. You don't want to run indefinite while loops inside messages, but in Actor Core itself it's a great way to do things.

 

In fact, I'd go as far as to say it's the right way of servicing external "things" like a bus writer, DAQ hardware, etc. I don't want my time-sensitive, possibly resource intensive processes being handled with my messages. For a DAQ actor, for example, all of the reading of the DAQ device itself is handled via a Helper loop, then passed internally to the rest of the Actor via messages it sends itself. Doing actual DAQ reads via the main queue would require the "Read" method to execute itself after each time it runs, which means the whole thing is always waiting on a Read operation to complete (since DAQ timing is determined by DAQ hardware, not the PC). This means any new messages that arrive must buffer and wait on the current DAQ read to be finished.

 

With a Helper loop, that loop just runs and services the DAQ Read function. When it gets new data, it sends a message to itself to "do stuff" with the data. The message queue is kept empty as all messages sent to the DAQ actor happen nearly instantly.

 

Another nigh-mandatory use of helper loops is for UI actors. Yes, you could poll for button presses in a recurring message, but a helper loop with an event handler in it that self-dispatches messages for button presses is a much better way to handle that.

 

As for the OP's problem, this will be nearly impossible to debug without some code, but maybe this will help: Try MGI's Monitored Actors (https://www.mooregoodideas.com/actor-framework/monitored-actor/monitored-actor-2-0/index.html). This lets you log messages and will let you visualize the process happening in your system. You will be able to tell if a message actually got read when you think it did, or if the message actually was sent at all.

Message 4 of 14
(1,565 Views)

@BertMcMahan wrote:

@Jay14159265 wrote:

In a very broad sense, it is not good to use while loops in the actor framework. The reasoning is that as long as you are executing in a while loop on your actors 'class instance' you will never dequeue another message for that actor. You can think of the execution of all code on an actor instance as a thread, if you never release the thread the underlying actor messaging system (for a single actor) can never execute. 

 

A much better solution to using a while loop is to simply use the actor method to call itself ( by sending a call message to itself) based on some logic, this will create a while loop in the context of the actor instance and allow for you to dequeue the other messages between runs of the 'while loop'. 


I disagree. I've got helper loops in nearly all of my Actors and they work just fine. A helper loop runs in parallel to Actor Core. It doesn't matter what the helper loop is doing, the Actor still processes messages. You don't want to run indefinite while loops inside messages, but in Actor Core itself it's a great way to do things.

 

In fact, I'd go as far as to say it's the right way of servicing external "things" like a bus writer, DAQ hardware, etc. I don't want my time-sensitive, possibly resource intensive processes being handled with my messages. For a DAQ actor, for example, all of the reading of the DAQ device itself is handled via a Helper loop, then passed internally to the rest of the Actor via messages it sends itself. Doing actual DAQ reads via the main queue would require the "Read" method to execute itself after each time it runs, which means the whole thing is always waiting on a Read operation to complete (since DAQ timing is determined by DAQ hardware, not the PC). This means any new messages that arrive must buffer and wait on the current DAQ read to be finished.

 

With a Helper loop, that loop just runs and services the DAQ Read function. When it gets new data, it sends a message to itself to "do stuff" with the data. The message queue is kept empty as all messages sent to the DAQ actor happen nearly instantly.

 

Another nigh-mandatory use of helper loops is for UI actors. Yes, you could poll for button presses in a recurring message, but a helper loop with an event handler in it that self-dispatches messages for button presses is a much better way to handle that.

 

As for the OP's problem, this will be nearly impossible to debug without some code, but maybe this will help: Try MGI's Monitored Actors (https://www.mooregoodideas.com/actor-framework/monitored-actor/monitored-actor-2-0/index.html). This lets you log messages and will let you visualize the process happening in your system. You will be able to tell if a message actually got read when you think it did, or if the message actually was sent at all.


I appreciate the discourse here, and I would like to ask two questions:

 

1) You talk about using helper loops in your actors, do the helper loops generally have I/O tasks in them? 

 

2) When you make UI actors, where do you stick the event loop? 

______________________________________________________________
Have a pleasant day and be sure to learn Python for success and prosperity.
0 Kudos
Message 5 of 14
(1,555 Views)

Of course, ask away... I'm certainly no AF pro.

 

1- Yes, any IO that takes longer than a few milliseconds will go in a helper loop in Actor Core.

 

2- UI Event Loops also go in Actor Core. Look up MGI's Panel Actor; it's an absolutely wonderful tool. It uses helper loops in Actor Core to catch button presses, then you can either do some stuff in the helper loop (if it's very trivial and doesn't need to interact with anything) or you can just use Self Enqueuer and send yourself a message.

 

"Helper Loops" always go in Actor Core. I suppose you could put them in a subVI, but they never run in message payloads. Those would just be called a "loop"- AFAIK, most of the common usage of the term "helper loop" in this context refers to a loop running in Actor Core in *parallel* to the Call Parent Method Actor Core.

 

You do have to have communications between the two, however. Helper Loop to Actor is simple; you just use Messages you send from the helper loop to the actor itself. The reverse means you have to have a secondary channel. I normally use User Events. I'll create a Start user event in Actor Core prior to the main Actor Core loop starting, then store the event ref in the Actor's private data. In Stop Core, you fire the user event that will then shut down the loop.

 

(MGI's Panel Actors does that for you, which saves a bunch of boilerplate code and "just works". It also provides some "Initialized", "Panel Shown", "Panel Hidden", and other Events that your helper loop can respond to. One of my most favorite tools.)

 

Regarding IO- I do put most IO in helper loops, but it depends somewhat on exactly what you're doing. Most of my IO goes in helper loops because it's a semi-continuous process that needs to execute for many seconds, minutes, hours, or (in one case) weeks. If it's a one-off thing then I'll put it in a message. Otherwise you have a Message send a user event back to the helper loop and have the helper loop send something back. Usually I'm happy enough to just block during the IO if it's short and non-recurring.

 

One thing I'd caution against is handling your UI stuff *in* your Actor Core's helper loop. Yes, it's easiest initially to work in there, but I recommend storing all of the control refnums in the Actor's private data, and handle all actual displays or updates in Messages. It's a touch more work to get started but it'll pay off for any non-trivial UI's. For example, your Helper Loop won't have access to the Actor's private data once it starts, so it can't make context-sensitive decisions. I guarantee you'll also find that you need your Messages to manipulate the GUI in some way at some point, so doing it via refnum is a LOT easier than trying to send messages back to the helper loop via User Event.

 

Sorry for rambling a bit.. hope that helps, lol. Please also let me know if any of this either doesn't make sense or sounds like the wrong way to do it. I've gathered most of this from tutorials and toolkits I've seen online, so I could've misunderstood something, but I've been doing AF for about 5 years intermittently and this method seems to work very well.

0 Kudos
Message 6 of 14
(1,534 Views)

Thanks for all replies.

 

Unfortunately i'm not allowed to share complete code, but i can show you LIN actor.

It doesn't work, because i didn't place all TypeDefs, etc into project..

But i think it will give you a bit better insight of my issue.

 

So i have that thoughts too, that in helper loop LIN communication isn't complete, so when actor receive new frame list, and list immediatelly after that, new list is overwritten.

 

I put small time delay, before sending message to this LIN actor, and this help. But i don't like this solution.

Because, i have doubts, that this could also problem, if i increase number of lists i send to this actor.

So i need more practical solution.

 

Regarding monitored actor app, looks very good. Thanks for that.

But when i enable message logging, it seams that there is messages nonstop between actors, even if i set sending messages only when button is pressed.

 

Best regards.

0 Kudos
Message 7 of 14
(1,481 Views)

Have you looked at the order in which cases are executed? When you use Send Get_List_Of_Frames.vi in rapid succession, your message handler will enqueue "update list" twice before each enqueue one "Tx/Rx".

 

So the quick fix is to prioritize the message.

cordm_2-1683537396093.png

 

Going further, I think you should get rid of at least one loop. You can easily merge the user event loop and message handler. "update list" goes in the "List of Frames" event case and Tx/Rx in the timeout case. Then you can also remove the need for variants. The actual device communication does not access any properties of the actor, consider moving it to its own class. Is the iteration terminal supposed to work like that? Can tx/rx fail?

merged loopsmerged loops

 

The MH might be better for extensibility, but in the present state it is just confusing. You can add "states" by adding more user events.

 

Regarding the constant messages: which actor is sending them?

0 Kudos
Message 8 of 14
(1,466 Views)

Seams that prioritizing the message works. Thanks.

Actually, it is more consistent but still sometimes skip some frame.

But how you mean MH will enqueue 'update list' twice? Where you see that this happened twice?

 

Regarding moving communication to separate actor... Why so? I created this actor to handle LIN communication only.

 

I use helper loop to have possibility to extend communication if necessary and to keep style guidelines.

But yes, it could be merged into one loop only.

 

'Can tx/rx fail?'

Yes, i suppose error can occure at Rx/Tx, but ii'm not sure how to handle that.

If you can give advice, i would be grateful.

 

'Regarding the constant messages: which actor is sending them?'

I would like to withdraw that question, because i didn't noticed that LIN actor constantly sends received frames up to caller actor.

 

 

 

0 Kudos
Message 9 of 14
(1,462 Views)

Actually, it is more consistent but still sometimes skip some frame.


Take a look at the iteration counter, I do not think that is working as intended. Could this be the cause of skipped frames?

 


But how you mean MH will enqueue 'update list' twice? Where you see that this happened twice?

Not the MH, but the actor's caller. If "TX/RX" is currently executing and takes longer than it takes to send the updated list, the state machine queue looks like this (without priorization)

initial queue

[]

send updated list:

["update list"]

send another updated list:

["update list","update list"]

update list state executed

["update list","TX/RX"]

update list state executed again

["TX/RX","TX/RX"]

 


Regarding moving communication to separate actor... Why so? I created this actor to handle LIN communication only.

What I meant was to separate this

cordm_0-1683545204602.png

 

from the actor into its own class (not actor). It basically is its own class, just not formally. Your actor allow you to use this "class" in an asynchronous manner. The iteration counter can also go into the class. You might need to reset it in update Tx frames.

 


Yes, i suppose error can occure at Rx/Tx, but ii'm not sure how to handle that.


You would need to put error terminals on send receive (SubVI) to see the errors and then handle them.

 

0 Kudos
Message 10 of 14
(1,449 Views)