1

I have an event handler in a class which doesnt seem to trigger. I wonder if anyone had any ideas on why this may be happening (or not happening as is the case).

The class inherits from another class and basically listens for messages from a message queue. When a message hits the queue the method onMessage() is called.

From my (winforms, c#, .net 3.5) UI form, I'm trying to get the received message(s) back to the UI.

If I call the method onMessage() manually from the instance on my form, the eventhandler does trigger correctly and passMessage is executed on my UI form.

But when I receive a message thats come automated from the queue I'm listening on, the event handler is not triggered. I dont ever call the onMessage() method, that happens automatically.

Does anyone have any ideas why the event handler is not triggering when onMessage() is called everytime I receive a message?

Thanks

UI:

private void btnConnect(object sender, EventArgs e)
{
    MessageQueue myMQ = new MessageQueue();
    myMQ.Connect(...);
    //Register handler
        myMQ.MsgTrigger += new EventHandler(passMessage);
}

public void passMessage(object s, EventArgs e)
{
    Console.WriteLine(s.ToString()); //Not sure if this is a good way to pass back a value
}

Class:

namespace MQListener
{
    class MessageQueue : MQ.MessageListener
    {
        public event EventHandler MsgTrigger;

        public virtual void onMessage(MQ.Message Message)
        {
            MQ.TextMessage txtMessage = (MQ.TextMessage)Message;
            String MsgBody = txtMessage.getMessage();
            Console.WriteLine(MsgBody);

            object objMsg = (object)MsgBody;

            var _Trigger = MsgTrigger;

                if(_Trigger != null)
                   _Trigger(objMsg, null);
        }
    }
}
Developr
  • 447
  • 8
  • 21
  • _But when I receive a message thats come automated from the queue I'm listening on, the event handler is not triggered._ Does this run a background thread by any chance? If an exception is thrown here it might be eaten. – Slippery Pete Aug 22 '14 at 13:38
  • So your MessageQueue listens on MSMQ to receive messages? Can you share code/configuration how you made MessageQueue to listen on MSMQ? – Michael Aug 22 '14 at 13:39
  • It may run on a background thread. Im not sure Pete. – Developr Aug 22 '14 at 13:42
  • Hi Michael, its not MSMQ, its an enterprise ESB platform. all I have is a few DLLs and a basic example. MessageQueue class simply creates a session, connects to a queue and 'listens' to that queue for messages (the class being inherited from MQ.MessageListener takes care of everything, but I cannot see inside that class at all). When any messages arrive the 'session' must call onMessage() because I dont. But I guess the onMessage is coming from a different thread hence why my event handler is not working? – Developr Aug 22 '14 at 13:47
  • @Developr In that case try wrapping the contents of onMessage in a `try..catch` block, and `Console.WriteLine()` the exception. This will let you know if it's bombing out before it has a chance to trigger your handler. – Slippery Pete Aug 22 '14 at 13:55
  • @Developr of course it listens on different thread (otherwise, your UI thread would be blocked). Follow Pete's advise, wrap up everything in try/catch, also, add some logging/console.writeline at first line in OnMessage method, just to make sure your listener gets messages at all. One more thing to note - when you're triggering event, pass EventArgs.Empty instead of null. _Trigger(objMsg, EventArgs.Empty); – Michael Aug 22 '14 at 14:25
  • Hi, I wrapped everything in onMessage() in a try/catch but I was still receiving no errors and the event handler still was not triggering. I removed "if(_Trigger != null)" so that "_Trigger(objMsg, null)" is always called and then I received an error of "Object reference not set to an instance of an object". I checked and _Trigger always seems to be null. Does this mean the handler has no listeners registered against it? Im not sure? – Developr Aug 22 '14 at 15:31
  • @Developr Yes, if _Trigger is null that means there is no event handler attached. Perhaps you should attach your handler before connecting, in other words put `myMQ.MsgTrigger += new EventHandler(passMessage);` before `myMQ.Connect(...);`. – Slippery Pete Aug 22 '14 at 15:36
  • @Pete, aha! I moved that above and now I get the error you probably would expect.. "Cross-thread operation not valid: Control 'txtMessage' accessed from a thread other than the thread it was created on.". Is there a way around this? – Developr Aug 22 '14 at 15:44
  • Also the event handler now fires correctly and the function on my UI form (passMessage()) is triggered. Its just passing the objMsg through the handler to my form thats causing the cross thread error. – Developr Aug 22 '14 at 15:53
  • @Developr Yes, there is a way around that. See answer below - – Slippery Pete Aug 22 '14 at 16:56

1 Answers1

1
  1. Your event subscription should happen before you connect:

    private void btnConnect(object sender, EventArgs e)
    {
        MessageQueue myMQ = new MessageQueue();
        //Register handler
        myMQ.MsgTrigger += new EventHandler(passMessage);
        myMQ.Connect(...);
    }
    
  2. You can only update controls from the UI thread, so to prevent the error "'txtMessage' accessed from a thread other than the thread it was created on.", you need to check the control's InvokeRequired property. If true, you need to call the Invoke() method. See this SO question: Automating the InvokeRequired code pattern

Community
  • 1
  • 1
Slippery Pete
  • 3,051
  • 1
  • 13
  • 15
  • If you *know* that the code isn't going to be fired from the UI thread there's no need to check if you need to invoke, just unconditionally invoke. In the vast majority of applications you either know you'll be in the UI thread, or you know you won't be. You should pretty much never need to *check* if you need to invoke. – Servy Aug 22 '14 at 17:14