From 11:00 PM CST Friday, Feb 14th - 6:30 PM CST Saturday, Feb 15th, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
From 11:00 PM CST Friday, Feb 14th - 6:30 PM CST Saturday, Feb 15th, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
08-28-2015 03:27 AM
Hi. I am working on my first Actor Framework project.
It has been going fine so far, but now I have encountered a problem.
In my project I have the root actor start five nested actors, where only two of the five nested actors override the Actor Core.vi. The two which overrides Actor Core.vi is:
- A communication actor which is polling a COM port to check if the machine we work on is connected
- A GUI actor.
The communication actor inherits directly from Actror.lvclass.
The GUI actor is actiually two diffeerent actors which is never started at the same time. One is use for service operations on special service stations and the other for more common operations. But they share some common features, and thus I decided to make a GUI base class which inherits from Actror.lvclass. The two GUI actors then inherits from my GUI base class. I have overridden the Stop Core.vi for all the actor classes in which I have overridden the Actor Core.vi. So far so good.
Now the problem I have encountered is this:
When i start my application with one the two GUI actors and the communication actor running, and I attempt to close the application by stopping the root actor or one of the GUI actors (the result is the same), the communication actor dos not receive the stop message and thus its Stop Core.vi is never called. If however I do not start a GUI actor and I stop the application by closing the root actor, it works fine.
I should add that at first we only had one GUI actor, and at that time the GUI actor inherited directly from Actror.lvclass. That setup worked just fine with at shut down. It is only after I have refactored the GUI actor(s) to have this GUI base class that it stopped working.
I suppose it is a simple mistake I have done, but since I am new to the Actor Framework, I can't seem to see what went wrong.
Cheers
Jens.
08-28-2015 09:02 AM
Hi Jens,
you have to make sure, that all actors receive a stop message. An actor invoking subactors should provide also a decent way of stopping its subactors.
Which actor is supoosed to stop your communication actor? If it is the communication actors, where do they differ? Also note, that dynamic dispatching sometimes can play nice tricks on you
Oli
08-28-2015 09:08 AM
Maybe there is a Call Parent missing somewhere?
08-28-2015 09:17 AM
Jens,
Stopping nested actors is optionally built in, but there are some things to be aware of.
1. When launching a nested actor you can leave the Auto-stop? (T) connector unwired and then it will add the nested actor's enqueuer to an array of enqueuers that will all receive a stop message when the parent stops.
2. You can wire a False into the Auto-stop? connector and then you are responsible for stopping the nested actor. Prior to 2014 this was the way it worked. Then you would be responsible for storing the enqueuer of the nested actor and deciding when to stop it. Generally speaking you would add an enqueuer to the private data of the root actor and then bundle by name the enqueuer from the launch method. In Stop Core you would send a Normal or Emergency Stop to the nested actor. I still like to do this when I am controlling lifetimes.
3. If you stop a nested actor with a "Normal Stop" message it returns a last ack that doesn't have an error. So, if you stop the program from a nested actor you need to exit with an error code that causes Handle Last Ack to evaluate to an error and then stop you root actor which will then stop your other nested actors.
Casey
Phoenix, LLC
CLA, LabVIEW Champion
Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!
08-28-2015 09:21 AM
Jens,
I'm working on a very similar project where I have RS232 sensors which I want to poll, log and plot on a GUI. Although I don't have a great answer for your issue, I'll point you towards something I found yesterday-> Monitored Actors.
https://lavag.org/topic/17056-monitoring-actors/
You basically add the library to your project and have your Actors inherit from the Monitored Actor.lvclass instead of Actor.lvclass and at runtime it provides a really nice, additional interface allowing you to monitor, kill and even debug actors that are misbehaving. This has made it far less painful and you don't have to close LabVIEW everytime an Actor gets stuck in a loop.
Cheers,
Winston
08-28-2015 09:42 AM
Oli_Wachno wrote:
Maybe there is a Call Parent missing somewhere?
Unlikely. The "Must Call Parent" flag is on the Actor Core.vi, and that is sufficient to guarantee that Stop Core gets invoked. Stop Core also has "Must Call Parent." I can't think of any way this could ever be the problem (other than LV itself having a bug, but that seems unlikely in a code path this heavily traveled).
08-31-2015 04:06 AM
Hi,
Without actually seeing your code, I understood that closing the GUI actor should send a message to the root actor (or maybe you use the GUI actor's last ack instead) and the root actor should then send a stop message to itself to stop all its nested actors. Is this how you are handling the GUI stop?
Also, are you using LV14 with "Launch nested actor" with default "stop nested" to "true" or are you using another method?
Thanks,
Danielle
09-02-2015 02:02 PM
Hi Danielle.
Yes you understood it correctly, and I am using LV2014 with "Launch nested actor" with default "stop nested" to "true".
After spending a lot of time debugging I found out that it all came down to a race condition at application startup.
It turned out that my communication actor started producing messages for the GUI actor (using the root actor as relay) before the GUI actor core was ready. This would normally not be a problem in the Actor Framework, but in my case I need to get some data (the connection state) from the message Do.vi in to the UI data, which is all handled in an event structure in the GUI actor core. So I generate a User Event in the message Do.vi which is handled by the event structure in GUI actor core. But the race condition meant that the first message could fire the event before it got registered with the event structure which was suppose to handle it.
I do not know how this could have broken the messaging with the communication actor all together, but when I got this fixed the problem disappeared. I made a "GUI_Ready" message, which the GUI actor must send to the root actor after it has registered it User Events. The root actor then sends relevant messages to other actors which needs to wait for the GUI to be ready....
After I did this extra "debug review" I am not sure that I like the setup, but it works. Possibly I went down a wrong track when I decided to use User Events to move data in to my GUI data handling in the GUI actor, but it seemed like a reasonable and straight forward approach at the time.
But in general, how do you (all of you) handle issues like this, and are we not missing some mechanism in the Actor Framework to synchronize the execution of actor cores at custom points of execution, or have I missed some feature which is already present in the implementation?
Cheers
Jens.
09-02-2015 02:32 PM
J.C._Andersen wrote:
are we not missing some mechanism in the Actor Framework to synchronize the execution of actor cores at custom points of execution, or have I missed some feature which is already present in the implementation?
The primary aim of the AF is to not need synchronization between any actor cores. Trying to build such sync points proved so nasty to get right, it's one of the things that drove me to investigate actor programming in the first place.
> when I decided to use User Events to move data in to my GUI data handling in the GUI actor
Assuming I read this right, that's the recommended solution. You have a single GUI actor and you need to pass information from the message handling loop to the UI loop in your Actor Core, right? If that's correct, then firing user events is exactly the right way to do this.
Where you may have gone wrong -- you create the user event on the block diagram of Actor Core, right? You need to make sure that the Register For Event node is executed before the Call Parent node. Just serialize the calls with the error cluster and you should be fine.
09-04-2015 01:27 PM
Yes, you read it right that is what I am doing.
I am creating my user event in a sub VI in the Pre Launch Init.vi and storing the ref. in a type def. cluster in my GUI actor class. I then do the registration of the User Events on the block diagram of the Actor Core, and that part is serialized as you describe.
As you can see from the image I register one set of events from my child GUI class and one set from my parent GUI class.
And of cause it makes sense that the actor cannot receive or process any messages until the message handling loop of the parent is running. I totally get that now.
But this gets me more worried, because it means that I may not have found the original problem after all.
I have not been able to able to reproduce the problem since I created that extra "GUI Ready" message.
In the next picture you see a screen shot of my other GUI actor (selection of GUI actor is done offline in an ini file).
Here I have added a sub VI which sends the "GUI Ready" message. As I described in an earlier post this keeps the communication actor from attempting to sending messages to the GUI actor until the "GUI Ready" message is received. I may need to go back and undo my changes one by one, to see if I can reproduce the problem.
Cheers
Jens.