Reading and Receiving Messages

   

You can read and receive messages from the queues in your system in several ways. First, you can either receive messages from the queue or you can peek at the messages on a queue without removing them. You also can create an event handler that watches for a new message to arrive and automatically raises an event when the message arrives at the queue. The following sections explain each of these methods of working with queue messages.

You need to keep several considerations in mind when reading and retrieving messages. For example, when you perform a receive operation, you might want to temporarily prevent other users from also removing messages from the queue with which you are working. You can do this by setting the DenySharedReceive property on that queue to True. This setting prevents any other users from removing messages from the same queue until you release your use of it, either through garbage collection or by calling the Close() method.

Messages have a large number of properties, and filtering the properties you want to receive can enable you to focus on only the information that is relevant to you. For example, if you are not working with transactional messages, you might not want to retrieve the properties associated with transactions. In this case, you would set the MessagePropertyFilter properties IsFirstInTransaction , IsLastInTransaction , TransactionID , and TransactionStatusQueue to False. Your MessageQueue component instance would not retrieve any of the property values corresponding to these properties whenever it gets a message from a queue.

When you read messages from a queue, a Formatter object is used to serialize and deserialize the message's contents as you manipulate the message. By default, an XMLMessageFormatter object is associated with any instance of the MessageQueue component you create, and you can use this to receive messages by setting a few necessary properties on it. You can also use various other types of Formatter objects that are available to you.

The XMLMessageFormatter uses human-readable XML strings to persist objects and primitive data types into and out of messages. When you want to use this formatter to retrieve a message, you set a TargetTypeNames or TargetTypes property to indicate how the resulting message should be handled. You do not have to set both properties setting one or the other causes the value to be reflected immediately in the other. If you are using another Formatter object, the properties differ .

Specifying Properties to Retrieve with a Message

When you create an instance of the MessageQueue component, you can set a series of properties to indicate what properties you want to retrieve when the component gets a message from a queue. These properties exist in a class called MessagePropertyFilter and correspond to actual properties on the Message class. When you set the value for one of these properties to True, the component retrieves the corresponding property each time a message is removed from the queue.

If you do not need access to some properties in your retrieved message and want to improve performance, you can set the MessagePropertyFilter to False.

Specifying the Formatter for Retrieved Messages

You must indicate the Formatter object you want to use to retrieve a message from a queue. A formatter indicates how a message will be deserialized when it is removed from the queue. Depending on the type of formatter you use, you might need to set additional properties to specify how the formatter should proceed.

By default, you use the XMLMessageFormatter for most operations.

You can specify the formatter in code. In addition, you can set the formatter either on the queue or on the message. You set the formatter on the queue when you plan to access the queue's messages directly, as in the following code:

 ' Visual Basic  Console.WriteLine(cStr(MessageQueue1.Receive.Body))  // C#  Console.WriteLine(MessageQueue1.Receive.Body.ToString()); 

You set the formatter on the message when you plan to retrieve a queue's contents through the Message object:

 ' Visual Basic  Message1 = MessageQueue1.Receive  // C#  message1 = messageQueue1.Receive; 

To specify the formatter programmatically, follow these steps:

  1. Create and configure your MessageQueue component instance.

  2. In the Code window, create a Formatter object of type XMLMessageFormatter , ActiveXMessageFormatter , or BinaryMessageFormatter .

  3. Set any necessary properties for your formatter.

  4. Retrieve your message.

For example, the following code shows how to create and configure a component that uses the XMLMessageFormatter object to retrieve a message from a public queue called MyQueue :

 ' Visual Basic  Dim mq As System.Messaging.MessageQueue =  new System.Messaging.MessageQueue(".\MyQueue")  Dim formatter As System.Messaging.XmlMessageFormatter =  CType(mq.Formatter, System.Messaging.XmlMessageFormatter)  formatter.TargetTypeNames = new String(){"System.String"}  Dim m As System.Messaging.Message = mq.Receive(New TimeSpan(0,0,3))  // C#  System.Messaging.MessageQueue mq =  new System.Messaging.MessageQueue(".\MyQueue");  string[] types = { "System.String" };  ((System.Messaging.XmlMessageFormatter)mq.Formatter).TargetTypeNames = types;  System.Messaging.Message m = mq.Receive(new TimeSpan(0,0,3)); 

Receiving Messages Programmatically

You can use a synchronous method called Receive to look at the contents of a queue. When you call the Receive method on a queue, the system removes the first message from the queue and returns it to you. This message is no longer available to other components looking at the queue.

You also can look at the first message on a queue without removing it from the queue. You also can receive messages asynchronously.

If no messages are available on the queue when you call the Receive method, the method waits until a message arrives on the queue. You can specify a time-out period if you want the method to wait for only a specified interval. The time-out period is specified as a TimeSpan object.

When you read messages from a queue, a Formatter object is used to serialize and deserialize the message's contents as you manipulate the message.

There are several forms of the Receive method. The basic method has several overloads that enable you to specify things such as time-out periods. A method called MessageQueue.ReceiveById enables you to retrieve a particular message by its identifier. A method called ReceiveByCorrelationID enables you to retrieve a message by correlation ID.

To receive a message programmatically, do the following:

  1. Create an instance of the MessageQueue component and set its Path property to the queue to which you want to refer.

  2. Specify the formatter to use to retrieve your message.

  3. Create an instance of the Message object to hold the retrieved message.

  4. Call the Receive method to remove the message from the queue.

To specify a time-out for the Receive method, use a TimeSpan object to specify the length of time that you want the method to wait.

When you are finished, your code might look like this:

 ' Visual Basic  Dim mq As System.Messaging.MessageQueue =  new System.Messaging.MessageQueue(".\MyQueue")  mq.Send("1","1")  Dim m as System.Messaging.Message  m = mq.Receive(New TimeSpan(0,0,3))  m.Formatter = new XmlMessageFormatter(new string(){"System.String, mscorlib"})  Console.WriteLine(m.Body)  // C#  System.Messaging.MessageQueue mq =  new System.Messaging.MessageQueue(".\MyQueue");  mq.Send("1","1");  Message m = mq.Receive(new TimeSpan(0,0,3));  m.Formatter = new XmlMessageFormatter(new string[] {"System.String,mscorlib"});  Console.WriteLine(m.Body); 

Peeking at Messages

You can use the Peek method to look at the first message on any queue without removing that message from the queue. This allows your component to get information from the queue without preventing other applications or components from retrieving messages they were intended to process.

Peek enables you to see only the first message on the queue. Because that message is not removed from the queue when you peek at it, you cannot then peek at subsequent messages. If you want to see all the messages in a queue without removing them from the queue, you can use the GetMessages method or the GetMessagesEnumerator method.

If no messages are in the queue when you call the Peek method, the method waits until a message arrives. You can specify a time-out period if you want the method to wait only a specified period of time. The time-out period is specified as a TimeSpan object. Most commonly, the time-out period will be set to either zero, in which case it checks for a message and does not wait at all, or to the default infinite setting, which waits indefinitely. You set this in code using the following syntax:

 ' Visual Basic  msg.TimeToBeReceived = msg.InfiniteTimeout  // C#  msg.TimeToBeReceived = msg.InfiniteTimeout; 

When using dependent clients , be sure the clock on the client computer is synchronized with the clock on the server that is running Message Queuing. Otherwise, unpredictable behavior might result if you send a message whose TimeToBeReceived property is not InfiniteTimeout .

To peek at messages synchronously, do the following:

  1. Create an instance of the MessageQueue component and set its Path property to the queue to which you want to refer.

  2. Create an instance of the Message object to hold the data the Peek method copies from the queue.

  3. Call the Peek method to get data about the first message on the queue. Optionally, to specify a time-out for the Peek method, enter the length of time (as a TimeSpan object) that you want the method to wait as an argument of the method.

For example, the following code shows how you can use the Peek method to return and display information about the first message on a queue. This example assumes that you are working on a Windows forms application that contains a label called Label1, and that you are working with a queue called MyQueue.

 ' Visual Basic  Public Sub LookFirstMessage()     Dim NewQueue As New System.Messaging.MessageQueue(".\MyQueue")     Dim FirstMessage As System.Messaging.Message     FirstMessage = NewQueue.Peek     FirstMessage.Formatter = new XmlMessageFormatter()     cType(FirstMessage.Formatter, XmlMessageFormatter).TargetTypeNames =     new string(){"System.String, mscorlib"}     label1.Text = CStr(FirstMessage.Label)  End Sub  // C#  public void LookFirstMessage()  {     System.Messaging.MessageQueue newQueue = new      System.Messaging.MessageQueue(".\MyQueue");     System.Messaging.Message firstMessage;     string[] types = { "System.String, mscorlib" };     System.Messaging.Message firstMessage;     firstMessage = newQueue.Peek();     firstMessage.Formatter = new XmlMessageformatter(types);     Label1.Text=((string)firstMessage.Label);  } 

Asynchronous Message Processing

You can retrieve messages asynchronously if you want to retrieve messages without tying up your application's processing. In asynchronous message processing, methods start tasks and then return immediately to the caller without waiting for a result. The application can continue to do what it was originally doing while the task is completed. When the task completes, the server can notify the application that the message was successfully processed .

There are two types of asynchronous messaging operations: receiving messages asynchronously and peeking at messages asynchronously. When you retrieve a message asynchronously, you use the BeginReceive method and the EndReceive method to mark the beginning and end of the operation. The actions that occur are as follows :

  • The BeginReceive method returns immediately and raises an event called ReceiveCompleted when a message becomes available on the queue or if the message you are peeking at or receiving already exists.

  • The ReceiveCompleted method returns an object of type IAsyncResult that contains information about the asynchronous operation.

After the completed event is received, you call the EndReceive method to complete the operation. Within the end call, you might access the message or retrieve it by accessing the ReceiveCompletedEventArgs class.

You can access the IAsyncResult object throughout the lifetime of the operation, but typically you do not use it until EndReceive is called. However, if you start several asynchronous operations, you can place their IAsyncResult values in an array and specify whether to wait for all operations or any individual operation to complete. In this case, you use the AsyncWaitHandle property of the IAsyncResult object to identify completed operations.

Peeking, like receiving, uses two methods called BeginPeek and EndPeek to bracket the beginning and end of the asynchronous operation. BeginPeek returns immediately and raises an event called PeekCompleted when a message becomes available. Like ReceiveCompleted , this event returns an IAsyncResult object you can manipulate for information about the operation.

In addition, both asynchronous receive and peek operations can use a time-out period to specify how long you want to wait for a message to become available. To do so, you use an overloaded form of either method to pass a TimeSpan object that indicates the time to wait. The ReceiveCompleted or PeekCompleted event is raised if the time-out period expires , but the IsCompleted property on the IAsyncResult object is set to False to indicate that a message was not dealt with.

You can receive notification when your asynchronous receive or peek operation completes successfully in either of two ways:

  • You can create an event handler that handles the ReceiveCompleted or PeekCompleted events when they occur.

  • You can use a callback to automatically watch for incoming messages and pass processing to your application when a message arrives.

When you use event notification, you create a method that handles your message processing and returns a notification when the processing completes. You then call the method that begins the asynchronous processing. The system creates the event handlers for you automatically when you double-click your MessageQueue component in the Designer.

In the event-notification scenario, BeginPeek or BeginReceive returns a single message and then stops processing. You must call BeginPeek or BeginReceive again for each message you want to retrieve.

An alternative way to process messages asynchronously is to use a callback. A callback identifies a delegate you want to associate with your BeginPeek or BeginReceive operations. In this scenario, the delegate continues to watch for new event notification after each message is processed.

   


Special Edition Using ASP. NET
Special Edition Using ASP.Net
ISBN: 0789725606
EAN: 2147483647
Year: 2002
Pages: 233

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net