Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Receive Msg.vi

If I'm reading that right, your Event Reference isn't initialized/set before it's used.

 

Make sure that the event reference is correctly created using Create User Event, or handle the error 1 until it is created (it might be you know sometimes it will be used before initialized, in that case you must handle the error).


GCentral
0 Kudos
Message 11 of 21
(1,576 Views)

@mahalakshmi05 wrote:

Error will come only when "Message in" is not in the specified class, right? 


Yes. No error when the message is of the tested class. But if you test against an array of classes, then most of them will be errors (more than one can succeed if you have inheritance between messages, but that's unusual with Actor Framework I think). Usually 0 or 1 will be not errors, and the rest will be errors.


GCentral
0 Kudos
Message 12 of 21
(1,575 Views)

To More Specific Class does NOT work for this purpose; you need to use Preserve Run-Time Class.

 

While it is true that you can bundle different class types into an array, the output wire's type is that of the closest common parent.  When you are putting different messages into an array, the closest common parent's type is Message.lvclass.

 

To More Specific Class will try to cast your object to the type of the wire you connected to the Target Class input of To More Specific Class.  That type is "Message.lvclass", so your cast will always be successful.

 

Preserve Run-Time Class, on the other hand, will try to cast your object to the type of the object on the wire that you connected to the Target Object input.  Note the difference in input names:  Target Class vs. Target Object.  The target object is the actual message object at that position in the message array, which is what you want.  You'll get an error out if the object types don't match, and no error if they do.

Message 13 of 21
(1,568 Views)

@justACS wrote:

To More Specific Class does NOT work for this purpose; you need to use Preserve Run-Time Class.

 

While it is true that you can bundle different class types into an array, the output wire's type is that of the closest common parent.  When you are putting different messages into an array, the closest common parent's type is Message.lvclass.


Bother. Sorry, should have checked code rather than misposting.

Here's an image of some working code...

cbutcher_0-1623342091484.png

cbutcher_1-1623342113112.png

 

Hopefully I won't soon be told that this contains a bug too...


GCentral
0 Kudos
Message 14 of 21
(1,563 Views)

@justACS  escreveu:

To More Specific Class does NOT work for this purpose; you need to use Preserve Run-Time Class.

 

While it is true that you can bundle different class types into an array, the output wire's type is that of the closest common parent.  When you are putting different messages into an array, the closest common parent's type is Message.lvclass.

 

To More Specific Class will try to cast your object to the type of the wire you connected to the Target Class input of To More Specific Class.  That type is "Message.lvclass", so your cast will always be successful.

 

Preserve Run-Time Class, on the other hand, will try to cast your object to the type of the object on the wire that you connected to the Target Object input.  Note the difference in input names:  Target Class vs. Target Object.  The target object is the actual message object at that position in the message array, which is what you want.  You'll get an error out if the object types don't match, and no error if they do.


I was about to write something like that, but the answer couldn't be more complete. 

Comparing classes can be tricky.

0 Kudos
Message 15 of 21
(1,562 Views)

@cbutcher wrote:

Here's an image of some working code...

 


Thanks for posting that.  I didn't feel like getting my graphics game on this morning.

0 Kudos
Message 16 of 21
(1,560 Views)

I had similar thoughts, but wasn't 100% confident without firing up LabVIEW to check. I figured either someone else like Allen would respond or it just simply wouldn't work, which would prompt another post.

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
0 Kudos
Message 17 of 21
(1,556 Views)

Thanks a lot cbutcher, that helped to get more clarity. Sorry for troubling you with one more doubt. It goes like this...
If I am redirecting one of my messages which is originally sent to "Child 1" to the "Grandchild", should I have the same method and message created in the "Grandchild's prelaunch init" ? 

I have String message to be redirected, so i should have the user event created in both Child1 and Grandchild ?

0 Kudos
Message 18 of 21
(1,516 Views)

Thanks everyone for joining up in this discussion. It helped a lot. 

One more issue I am facing is, Whenever I send a message that needs to be diverted, the actor to be which I intend to divert my msg gets stopped. Error 1556 occurs. It says reference is invalid or deleted. But I have properly created the user event in pre launch init, registered it in my actor core too. I have attached the project file also.

0 Kudos
Message 19 of 21
(1,513 Views)

@mahalakshmi05 wrote:

Thanks a lot cbutcher, that helped to get more clarity. Sorry for troubling you with one more doubt. It goes like this...
If I am redirecting one of my messages which is originally sent to "Child 1" to the "Grandchild", should I have the same method and message created in the "Grandchild's prelaunch init" ? 

I have String message to be redirected, so i should have the user event created in both Child1 and Grandchild ?


If you redirect a message, then the (newly) receiving Actor needs to be able to handle it. More generally, any Actor receiving any Message should know how to handle that message, or should handle the error smoothly...

Usually this is handled by only sending messages to an Actor that you know it can handle.


This is true regardless of a class inheritance between the (newly) sending Actor and the receiving Actor (child and grandchild here).

However, if the message is designed for a class A, and class B inherits from A, then B should be able to handle the message too, because the cast (in "Some Msg.lvclass:Do.vi") will be to class A, and class B will succeed in that conversion. If the VI invoked in Do.vi is dynamic dispatch and overriden by B, you'll get the B implementation, but otherwise it will fall back on the A implementation.

However, you haven't implemented an inheritance hierarchy. You instead have only a Caller/Callee relationship between "Child" and "Grandchild" (a misleading naming in this case, because it suggests inheritance, at least to me).

 

This isn't inherently a problem, but it does mean that when B (grandchild 1) receives a message M (e.g. Child 1.lvlib:Msg Child Msg.lvclass) sent by A (child 1), it has no idea what to do with it (which causes an error).

 

You could solve this by one of (and probably more options...)

  • Option 0) Don't send messages to Child 1.lvclass that aren't either handled by Child 1 (because no error in the Receive Msg override tests) or possible to handle in GrandChild 1. In your case, this probably means sending "Message GrandChild Msg" to Child 1 from Parent, but this means that Parent must know that GrandChild 1 is the intended recipient, and Child 1 will only be forwarding the message.
  • Option a) don't override Receive Message, but instead in Message Child.vi, send a new message (Message Grandchild Msg) to the "grandchild" with the same data that you get as a parameter to that function
  • Option b) rewrite Message Child Msg to allow either a Child 1.lvclass or a GrandChild 1.lvclass to handle it. This probably involves handling the error when it tries to convert Actor to Child 1.lvclass, and then try do the same for GrandChild 1. Pretty messy, and not a great choice in LabVIEW 2020...
  • Option c) Make GrandChild a child of Child (inheritance, not related to caller/callee setup), and make the VI called in Do.vi dynamic dispatch. At the moment, you have two different messages, calling two different VIs.
  • Option d) (LabVIEW 2020+ only) use interfaces.
    • Define an interface that allows receiving a string ("Update String.lvclass", or something) and then have both Child 1.lvclass and GrandChild 1.lvclass inherit from this interface (right click on the class in the Project Explorer, go to Properties, then the Inheritance tab on the left, then "Change Parent Interfaces").
    • Now make your message target the VI defined by the interface (if you use the name "Update String" for the VI in the interface, the message will be by default named "Update String Msg.lvclass", and in the Do.vi it will try to use To More Specific Class with the top input as "Update String.lvclass" - the interface).
    • Override "Update String.vi" in both Child 1 and GrandChild 1 classes, potentially doing something different in each case. The two classes in this case have nothing to do with each other, and don't need to know about the other's existence (at least for this - C will know about G if it launches G using Launch Nested Actor) - they just happen to both be able to receive the same Update String Msg class and handle it correctly.
    • This will allow you to, if you want, forward the message from Child 1 to GrandChild 1, and/or handle it directly in Child 1.

This was a fairly long post, but hopefully it gives you something to read and you can make some progress or gain some understanding. I'm sure someone will correct any errors that I missed or miswrote 🙂


GCentral
0 Kudos
Message 20 of 21
(1,507 Views)