Event Handler Order

This comes out of some testing I was doing involving this thread, but I discovered something new, so new thread.

Essentially what I was testing was the discovery that NetLinx runs all handlers for an event before checking the wait lists, whereas I had been under the impression that it occurred between each event handler.

In my test code, for each handler, I was calling a WAIT 0 (which expires immediately).
// IN MAIN
CHANNEL_EVENT[vdvDevice, 1]
{
   ON:
   {
      SEND_STRING 0, "'MAIN HANDLER START'";

      WAIT 0
      {
         SEND_STRING 0, "'MAIN HANDLER END'";
      }
   }
}

// IN MODULE 1
CHANNEL_EVENT[vdvDevice, 1]
{
   ON:
   {
      SEND_STRING 0, "'MODULE 1 HANDLER START'";

      WAIT 0
      {
         SEND_STRING 0, "'MODULE 1 HANDLER END'";
      }
   }
}

// IN MODULE 2
CHANNEL_EVENT[vdvDevice, 1]
{
   ON:
   {
      SEND_STRING 0, "'MODULE 2 HANDLER START'";

      WAIT 0
      {
         SEND_STRING 0, "'MODULE 2 HANDLER END'";
      }
   }
}

I expected to see this in diagnostics:
MAIN HANDLER START
MAIN HANDLER END
MODULE 1 HANDLER START
MODULE 1 HANDLER END
MODULE 2 HANDLER START
MODULE 2 HANDLER END

But instead saw this:
MAIN HANDLER START
MODULE 1 HANDLER START
MODULE 2 HANDLER START
MAIN HANDLER END
MODULE 1 HANDLER END
MODULE 2 HANDLER END

So when the event comes out of the message queue it's:
CHANNEL 1 ON
- RUN HANDLER 1
-- PLACE WAIT 1 ON WAIT LIST
- RUN HANDLER 2
-- PLACE WAIT 2 ON WAIT LIST
- RUN HANDLER 3
-- PLACE WAIT 3 ON WAIT LIST
CHECK WAIT LIST
- RUN WAIT 1
- RUN WAIT 2
- RUN WAIT 3
NEXT EVENT...

This image (and corresponding tech note) essentially explains that, but I had always thought of each handler as being on the message queue when in fact the message is "CHANNEL 1 ON" and each handler is run as part of that message.

The thing that I found really interesting was when I added a 0 "catch all" wildcard handler:
// IN MAIN
CHANNEL_EVENT[vdvDevice, 1]
{
   ON:
   {
      SEND_STRING 0, "'MAIN HANDLER START'";

      WAIT 0
      {
         SEND_STRING 0, "'MAIN HANDLER END'";
      }
   }
}

CHANNEL_EVENT[vdvDevice, 0]
{
   ON:
   {
      SEND_STRING 0, "'MAIN ALL HANDLER START'";

      WAIT 0
      {
         SEND_STRING 0, "'MAIN ALL HANDLER END'";
      }
   }
}


// IN MODULE 1
CHANNEL_EVENT[vdvDevice, 1]
{
   ON:
   {
      SEND_STRING 0, "'MODULE 1 HANDLER START'";

      WAIT 0
      {
         SEND_STRING 0, "'MODULE 1 HANDLER END'";
      }
   }
}

CHANNEL_EVENT[vdvDevice, 0]
{
   ON:
   {
      SEND_STRING 0, "'MODULE 1 ALL HANDLER START'";

      WAIT 0
      {
         SEND_STRING 0, "'MODULE 1 ALL HANDLER END'";
      }
   }
}


// IN MODULE 2
CHANNEL_EVENT[vdvDevice, 1]
{
   ON:
   {
      SEND_STRING 0, "'MODULE 2 HANDLER START'";

      WAIT 0
      {
         SEND_STRING 0, "'MODULE 2 HANDLER END'";
      }
   }
}

CHANNEL_EVENT[vdvDevice, 0]
{
   ON:
   {
      SEND_STRING 0, "'MODULE 2 ALL HANDLER START'";

      WAIT 0
      {
         SEND_STRING 0, "'MODULE 2 ALL HANDLER END'";
      }
   }
}

Since I had placed my wildcard handlers after the explicitly defined ones I assumed event order would also place the wildcard diagnostic text after the explicitly defined ones.

To my surprise I got this:
MAIN ALL HANDLER START
MODULE 1 ALL HANDLER START
MODULE 2 ALL HANDLER START
MAIN HANDLER START
MODULE 1 HANDLER START
MODULE 2 HANDLER START
MAIN ALL HANDLER END
MODULE 1 ALL HANDLER END
MODULE 2 ALL HANDLER END
MAIN HANDLER END
MODULE 1 HANDLER END
MODULE 2 HANDLER END

The Language Reference Guide states "More than one handler can be defined for the same event. In this case, the handlers are executed in the order in which they are defined in the program.", but keep in mind, a wildcard event handler runs before any other explicitly defined handler for that channel regardless of order.

Enjoy!

Comments

  • PhreaKPhreaK Senior Member Posts: 966
    Nice finding. Thanks for the awesome write-up and clear explanation.
Sign In or Register to comment.