Jump to content

John Lokanis

Members
  • Posts

    797
  • Joined

  • Last visited

  • Days Won

    14

Posts posted by John Lokanis

  1. Dave: Yes, that is basically it.  When the parent quits, a local user event is fired to tell the UI loop to quit.

    Yes, all my "actors" inherit from that parent.  Think of it like the Actor Core in AF.  The parent handles all messages for that 'Actor'.  It also contains all state data.  Inside the parent code, I use dynamic dispatch to execute the various messages received.  The UI loop is a 'helper', not another 'actor'.

    I have implemented override-able error handling within the parent message code.  My 'helper' UI loop simply sends errors to the message handler to be dealt with.

     

    It occurs to me that my only solution might be to have the 'helper' UI loop call the error handler directly instead of passing it to the message handler.  That might mean I cannot reuse my error handler method as easily as I wanted to.

     

    Also still leave me with the need to stagger the shutdown for the error logger so it can catch any shutdown errors from the other processes.

  2. As for sync/async, I handle this by having a request message that contains the name of the sender.  The receiver then executes the message, gets the requested data and then sends a different message to the requester with the answer inside.  The requester executes this message containing the data, taking whatever action needed the data to perform its work.  This allows the requester to perform other actions (like a shutdown) while waiting for the data it requested.

    (dammit, not you got me going off topic...   :frusty: )

  3. Just to clarify a few points:

    I am not using Actors. I have created my own messaging system based off the way I did things pre-LVOOP.  All my processes (Actors, if you will) are peers.  There is no top level.  They can all message each other directly.  All messages are async.  The issue really is when one of these processes contains more than one loop running in parallel.  I took my design from the examples for implementing a UI with AF.  The UI code has its own loop, but the code also calls the parent class in parallel where the message handler is implemented.  The issue comes from trying to deal with errors at shutdown between the child implementation containing the UI loop and the parent message handler.

    I understand Dave's solution and I agree that sequencing a shutdown makes sense among the various processes (Actors) but I am still stuck with this case where we have overridden the parent message code to add a UI.  It still seems like there is no clean way to deal with this.

  4. Just to steer this back on topic, I still do not see a way for an 'Actor' that implements parallel loops to deal with an error when shutting itself down.  The AF uses these parallel loops to implement user interfaces.  But, if the UI code generates an error, it must send it to the message handler loop to process it.  And on shutdown, that loop has stopped.

     

    To be more specific, the user commands the UI to shutdown the system.  The UI loop broadcasts the shutdown message to all processes.  One of the calls to a different process fails because of some error with its message transport.  That error is returned from the 'send to all' call up to the UI loop.  The UI loop then tries to send that error to its message handler but since it received and executed the shutdown message, it is no longer running.

    The end result is I am unaware of a bug in my code where one of my processes has a bad message transport (for whatever reason).

     

    You all seem to be telling me that I should just ignore this issue.  I would prefer to find a solution but it does not look like there is one.

  5. ...error management...

    How does your error management work?  Do your parallel processes handle their own errors or do all errors get dispatched to a central error handler?

    At first I planned to use a central error handler, but that would create a bottleneck that would block all processes when many errors occurred at once and could lead to deadlock.  So, instead I have each process handle its own errors and only use a central process for logging.

    But, this leads to my current problem of the process not being able to handle its own shutdown errors.

    I could just ignore them (that is effectively what happens now) but I am concerned that would mask other issues.

  6. I am trying to solve a bit of a chicken-egg issue with my message system.  Since I think this would apply to any message system, I would like to hear how others have addressed this issue.

    In my message system, each parallel process has a message handler loop that receives and executes messages.  A process can also have code that runs in parallel with the message handler to implement additional functionality, such as a UI loop that handles events.

    If an error occurs in this UI loop, it sends the error to its message handler.  The message handler then executes the message with the error information, outputting the error as if it happened within the message loop.  This then propagates to an error handler that executes specific error handling code for that process and then sends the error info to an error logger process.

     

    I also have implemented a broadcast message to shutdown the application.  This sends the shutdown message to all processes at the same time.

     

    The problem I am running into occurs if an error is generated in the UI loop when it tries to send the shutdown message. That error is not getting handled.  This is because the message handler gets the shutdown message before the UI loop has a chance to send the error data.  So, there is nothing listening to the error message.  And even if it was still listening, the error logger process has also already shutdown so the error would not be logged either.

     

    So, any ideas on how to solve this?  How do you deal with this in your messaging systems?

     

    thanks for the feedback,

     

    -John

  7. Thanks for the ideas guys!  I have put together my solution pulling from all of them.  I decided to make the child window deal with the mouse tracking instead of the parent.  So, once it it created, it is on it's own.  Seemed simpler this way and frees up the parent to do other things.

    I tried to eliminate all polling by using the mouse enter and leave events but a fast mouse movement could still mess things up so I added the timeout polling to make it smoother overall.

     

    The target for this code will have the child subscribe to the same message stream that the parent uses to update each row of the MCLB, but with more details displayed.  Should make for a nice UI.

     

    Drag to Snap off Window.zip

     

  8. Ok, first, I don't even know if this is possible.  I have been messing with it for a few hours and have hit a brick wall.  I hope someone knows a trick or two to help me make this work.

    Here is what I am trying to do:

     

    When a user drags on a row of a MCLB, I want to dynamically open a VI under the user's cursor (their mouse button is still down) with 50% transparency and allow them to continue to move the mouse to drag the new VI's front panel to someplace on the screen and then release the mouse button.  At that point, the transparency will return to 100% and the window will act normally until they close it.

    The goal here is to allow them to access additional data that is related to the row they dragged on.

     

    The problem: Opening the VI a the location of the cursor when the drag starts is not a problem.  But getting it to track the mouse until the button is released is not working for me.  I cannot find any way to do this within the methods that LabVIEW offers.  Perhaps there is a .NET or Win32 solution?

     

    thanks for any ideas (or for telling me what I want to do is impossible).

     

    I will post a solution here if I get it working.

     

    -John

  9. I have been asked to implement some sort of online/integrated help system into my executable. I have not done anything like this before. (In the past I have just written word docs and published them on the internal network)

    I was wondering what the best practices were for doing this. A few ideas I had were:

    • Building .chm files and then linking them to controls and menus in my application. (not sure exactly how to do this).
    • Using tip strips to supply documentation.
    • Using a pane on the window to display help messages when requested or when hovering over certain controls.
    • Linking to a Wiki on the corporate network.

    I would prefer a solution that was mainly 'on demand' so advanced users would not be bothered by obtrusive help messages.

    Have you implemented built-in help? What worked best for you?

    Thanks for your ideas!

    -John

  10. ok, so this is weird. If you take the grandparent wire with the parent object riding on it and cast that to the parent type, you can use the parent accessors to get at the data in the parent object.

    But, if you take the grandparent wire with the parent object riding on it and you cast it to the child, then try to use the parent accessors available to the child class (I made them protected), you don't get the data. It comes back empty. Turns out, this is because the cast fails. But this was not obvious to me at first because I did not get an error message, even though I have automatic error handling turned on.

  11. you can cast the grandparent wire to parent wire using a "to more specific class" node and then call the accessors.

    That s what I did. But that means I needed a static parent object on the BD of the child method. I assume that means I had to allocate the memory for the parent's private data even though I did not use it. Seems inefficient to me. I would rather use the child wire to accomplish that. But this gives me an idea I need to go try now...

  12. aren’t messages and processes entirely different things.

    The architecture I am trying to design is one of a process that has a defined API. So, instead of having a method for each thing the process can do, it has a message (API call) that it can process. So, it made sense to me that these would be children of the process since they were exclusive to the process and operated on the process' private data. Also, by having them be children, I can use the inheritance mechanism to allow my message system to detect what process owns them and then route the message to the process using its chosen transport automatically.

    Again, this may turn out to be a bad idea, but I am going to try going down this road as far as it will take me until I make it work or decide it is the wrong road.

    The best you can do is created protected class data accessors in the parent class and use them in the child class to get at the class data.

    So I have created those accessors in the parent, but the wire type coming into the child is of type grandparent. So, I don't have access to the parent methods without casting it to the parent's type. I was hoping there was a way to do this using the child class wire. But I cannot sort out how to do this.

  13. Well, it is kinda complex, but here goes:

    I am trying to make a messaging system that uses the class hierarchy to route messages and has a plug-in type of implementation for routing methods.

    So, I have three main classes: System, Process and Transport.

    System holds a DVR containing an array of Process classes.

    Process holds a Transport object.

    Specific transports types (local queue, remote network message, notifier, etc) inherit from the transport class.

    Specific processes inherit from the process class.

    Each specific process class has child messages that implement create, send and execute methods.

    First, you instantiate an object of type System and create the DVR to hold the data.

    Next, you create a transport object for the specific type of transport you want a process to use.

    You then create a object for the specific process that will use that transport and store the transport in the process's (parent) private data. You also add this process object to the system object DVR.

    Later in your application, you create a instance of the specific process (can be the same as the object used to set the transport, or just another instance) and you set any initial conditions (this specific process, called the parent in the original email, stores any data needed to be accessed between messages). This then passes to a loop that waits for a message using the transport type set for that process and then calls the execute method for the message sent.

    The advantage of this is almost everything in the architecture is reusable. You just define the specifics by creating you specific processes and their messages and a transport implementation.

    The disadvantages are you can only have one implementation of a specific process class in each application instance.

    The other disadvantage is I cannot figure out how to cleanly access the data in the specific process (the parent) from within the execute message method. I have for now cast the process object to the type of the specific process but I would rather do this a better way.

    I included a zip of the demo project so far. Feel free to tell me this is a crazy way to solve this problem.

    Message System.zip

    -John

  14. I have a hierarchy of classes. Call them Grandparent, Parent and Child.

    I have a dynamic dispatch VI in grandparent that child overrides.

    In the child implementation, I want to access data in the parent class control.

    The template in the grandparent has two inputs of type grandparent. The dynamic one and a static one. The dynamic one is used to dispatch to the correct child.

    (this is because grandparent has more than one parent sub class and these have more than one child subclasses)

    The static one is used to pass in a parent object so the child has access to its data between calls. (the child is actually a message not spawned from the original parent object and therefore does not contain this persistent parent data)

    What I need to do is cast the grandparent wire to the type of parent so I can access the parent's data. I could use the child to do this but how do I extract the parent class type from the child and use it to cast the grandparent to type parent? I need to do this statically as design time, not at runtime.

    thanks for any ideas.

    -John

    An alternative solution would involve having the child (message) object inherit the data in the parent object so I could access it via property nodes. Not sure if that is possible.

  15. But haven't we discussed this before?

    Yes. But I ran into this again when working on my architecture. I really want to keep this simple. That is why I want the VI Server implementation to work. It lets me do messaging without having any code on the reciver side specific to the transport. I just call the local vi and stuff in the message. Simple and elegant, but not bulletproof unfortunately...

  16. If I can get this all sorted, I will post the example. It is part of an architecture I am trying out where each process in an application registers a transport with which to receive messages. So, when a message is sent, the system determines what process owns it and then uses the selected transport to send it.

    The cool thing is, both the sender and receiver contain each process's class and all its messages. For networked messages, the sender simply registers the process with a network transport and does not implements a process loop to handle messages. On the receiver side, the same process is set to use a local queue for messages and we do implement a loop to handle messages. The sender's transport code simply puts the message into the receiver's local queue. The neat part is any process can receiver local and remote messages. And I can move a process from the receiver to the sender by simply implmenting a process handler loop for it and by changing its transport from remote to local.

    The idea is to treat the messages as an API for each process. But, since I am still working out the details, I have not shared any of it yet. This VI Server issue came up as I was implementing my idea for the remote transport. But, I could easily replace that code with something else that gets the message from the sender to the receiver's queue.

    One drawback is each application instance can only own one copy of a process type. (messages determine their destination by process type, not the actual owning process object)

    Also, I have not sorted out a clean way to deal with local data within a process loop. But I think this can be done elegantly.

    thanks for the ideas. I will see if I can make something workable.

    Maybe you should use a central message “broker”, with all servers and clients connecting via the broker. Then there is only one connection per process. I think Shaun’s Dispatcher works this way, if I recall right.

    That just creates a single point of failure. Something I cannot do in this system as the cost of it failing is expensive. I can live with one server going down or one client, but not something central to everything.

  17. In my application, The client would open a connection to the server using VI server (open app ref, open VI ref, call VI). The server would have been up and running for some time before this so it is not in the startup state. The client too could have been up for some time and was making the connection due to some user actions. The server is unlikely to block the root loop since it is headless. But the client could easily block messages from the server by the user taking an action (drop down a menu) or a system dialog box being active. This would cause the server to be hung while it waits to execute the send message operation.

    I was planning to have the server cache the client machine name and port for sending replies, but I suppose I could cache a reference instead so the only block-able action would be the initial connection establishment. Now it becomes a problem of risk and mitigation. Still, I would like to eliminate the risk altogether.

  18. The end goal is a system where there are N servers and N clients. Each client can connect to N servers at the same time. Servers support N connections from clients simultaneously Servers 'push' data changes to the clients. Clients send commands to servers to control them. The data is mostly small but there are some circumstances where it could be around 1M. But that would not be continuous. Only once a minute or less. Most of the time the messages will contain a few k of data at most.

    Clients will drop off from time to time and the servers will automatically detect this and stop sending to them.

    Clients will know the machine names of the servers and will contact them to start a connection.

    I really wish the VI Server method was feasible. It is by far the simplest and cleanest.

    I will look at those examples. thanks,

    -John

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.