The goal is to listen indefinitely for a message to arrive on a queue and then handle that message. While you are waiting in the “listening” state, you don’t want to tie up resources.
For MSMQ, you register a callback method with the PeekCompleted event provided. Then call the BeginPeek method and you can now continue with processing something else while you let that “thread” wait for a message to arrive. When a message arrives on the queue, the call back method you assigned is executed and you grab the message with the Receive() method.
I needed an adapter for .NET clients to listen to WMQ for messages indefinitely that would be similar to the syntax used for consuming MSMQ messages. I never found (doesn’t mean it doesn’t exist) a way provided by Websphere to implement this with the dll’s they provide for .NET implementations. Here is what I came up with…
Below you’ll find:
- WMQQueueListener class: Listens to Websphere MQ indefintely for a particular QueueManager and Queue that you have connected to. I can provide connection code, too, if you ask nicely and leave a comment below. This class holds the event used.
- OnMessage method: A callback method you will create to handle the message you receive from MQ. The name of this method was chosen to be the same as that provided by the java side Websphere MQ implementation. I added the message in the args passed in to this method.
- WMQPeekCompleteEventArgs class: The event args that send the body of the message to your callback method.
- Main method: An example for how to setup the listener and register the OnMessage method to be called when a message arrives.
/// <summary> /// C# class for exposing a listener/poller for WMQ .NET clients. /// </summary> public sealed class WMQQueueListener { public event EventHandler<WMQPeekCompleteEventArgs> PeekMessageCompleted; protected void BeginPeekMessage(MQQueueManager queueManager, MQQueue queue) { // Setup MQ GetMessageOptions & Message MQGetMessageOptions options = new MQGetMessageOptions(); options.Options = MQC.MQGMO_FAIL_IF_QUIESCING | MQC.MQGMO_WAIT; options.WaitInterval = MQC.MQWI_UNLIMITED; MQMessage mqMessage = new MQMessage(); // Wait for message queue.Get(mqMessage, options); // Fire event OnPeekMessageCompleted(mqMessage); } private void OnPeekMessageCompleted(MQMessagemqMessage) { if (PeekMessageCompleted != null) { // Create event args for event/eventhandlers WMQPeekCompleteEventArgs peekCompleteEventArgs = new WMQPeekCompleteEventArgs(); peekCompleteEventArgs.Message = mqMessage.ReadString(mqMessage.MessageLength); // Fire "found message" event PeekMessageCompleted(this, peekCompleteEventArgs); } } } /// <summary> /// C# class for to allow the event fired by the WMQQueueListener /// to send the message it received back to a subscriber. /// </summary> public class WMQPeekCompleteEventArgs : EventArgs { public WMQPeekCompleteEventArgs() { } private string _message; public string Message { get { return _message; } set {_message = value; } } } // Callback method similar to PeekCompleted handler in MSMQ, but named for // Websphere's implementation. public void OnMessage(Object source, WMQPeekCompleteEventArgs args) { try { string body = args.Message; // TODO: Process the message you receive here } } // Test your work here static void Main(string[] args) { WMQQueueListener inputQueueListener = new WMQQueueListener(); // TODO: Need to test whether a connection is available to WMQ inputQueueListener.PeekMessageCompleted += OnMessage; inputQueueListener.BeginPeekMessage(queueManager, queue); // Here you can go about other business while the listener waits // to fire the OnMessage you create (similar to PeekCompleted for MSMQ). } I admit this needs some cleanup with logging and exception handling, but the main points are here. If you are interested in more please comment and I'll see what I can do.