Visual Basic Code Example: Reading Messages Asynchronously
The following example provides three Sub procedures for asynchronously reading the messages already available in a specified queue and any messages arriving in the queue until a known time period elapses without the arrival of a new message. The first procedure enables notification of message-arrival (MSMQEvent.Arrived) and arrival-error (MSMQEvent.ArrivedError) events, and the second procedure is an Arrived event routine for reading the messages. In this example each message is read and removed from the queue. The third Sub procedure handles an ArrivedError event by displaying a message indicating the nature of the error and terminating the process.
An application implementing these three Sub procedures will continue to receive messages sent to the specified queue until the receive time-out period specified in the call to MSMQQueue.EnableNotification elapses without the arrival of a new message. In this example, the receive time-out period is 10 seconds, but it can be set to any number of milliseconds or to INFINITE.
For more information about reading messages asynchronously, see Asynchronous Reading.
To enable notification
In the enable notification procedure, declare the objects needed to enable notification. Note that the MSMQEvent object is declared with events outside of the Sub procedure. The MSMQQueue object must also be declared outside of the scope of the Sub procedure; otherwise, it will be closed automatically and the arrival notification will not reach the applicable user-implemented event handler.
Obtain an MSMQQueueInfo object. The following example obtains the MSMQQueueInfo object by attempting to create the queue, ignoring any errors if the queue already exists.
Call MSMQQueueInfo.Open to open the queue with receive access. When opening a queue with receive access the application can peek at or retrieve the messages in the queue. As a result of this call, the opened queue is represented by the MSMQQueue object.
Create the object providing the Arrived and ArrivedError events and call MSMQQueue.EnableNotification to start notification, specifying the MSMQEvent object and setting the receive time-out period to 10000 milliseconds.
To handle Arrived events
In the Arrived event handler, declare the MSMQMessage object.
The New keyword cannot be used when reading messages.
The MSMQEvent object is declared outside of the Sub procedure with class-level scope because it must be available to both the part of the code that enables notification and both event handlers. Thus, the Arrived event handler remains active even after ReadDestinationQueueAsync has exited because the MSMQEvent object is owned by the form, which continues to run. If this code were to be cut and pasted into a class object, the lifetime of the class instance would determine the lifetime of the MSMQEvent object. The asynchronous handler would become unavailable as soon as the object is destroyed.
Similarly, the MSMQQueue object is declared outside of the scope of the event handlers so that it will not be closed automatically and the event notifications will reach the applicable user-implemented event handler.
Call MSMQQueue.Receive to read the message that triggered the event.
Cal MSMQQueue.EnableNotification to restart notification.
This example uses the default setting for the optional cursor parameter. If the cursor parameter is set to another value, be sure to coordinate how the cursor changes when reading the message and when enabling notification. Both operations affect how the cursor is moved.
For information about cursor movement, see Cursors and COM Components.
To handle ArrivedError events
In the ArrivedError event handler, ascertain whether the event was fired because the receive time-out period elapsed without the arrival of a new message or because some other error occurred.
Display a message indicating the nature of the error causing the event.
End the process.
The following code example can be run on all versions of Message Queuing.
' Declare Message Queuing objects Dim q As MSMQQueue Dim WithEvents qevent As MSMQEvent Private Sub ReadDestinationQueueAsync( _ strPathName As String _ ) Dim qinfo As New MSMQQueueInfo ' Set the path name in the MSMQQueueInfo object. qinfo.PathName = strPathName On Error Resume Next qinfo.Create On Error GoTo ErrorHandler ' Open the queue with receive access. Set q = qinfo.Open(MQ_RECEIVE_ACCESS, MQ_DENY_NONE) ' Create the receiving event. Set qevent = New MSMQEvent q.EnableNotification Event:=qevent, ReceiveTimeout:=10000 ' Start a DoEvents loop to prevent the thread from exiting. Dim wait As Long For wait = 1 To 10000 DoEvents Next Exit Sub ErrorHandler: MsgBox "Unexpected error!" + Chr(13) + "Reason: " + Err.Description _ + Chr(13) + "Error: " + Hex(Err.Number) End Sub Private Sub qevent_Arrived(ByVal q As Object, ByVal lCursor As Long) Dim msg As MSMQMessage On Error GoTo ErrorHandler ' Read the message that fired the Arrived event from the queue. Set msg = q.Receive(Transaction:=MQ_NO_TRANSACTION, ReceiveTimeout:=0) If Not msg Is Nothing Then MsgBox "Removed message from the queue." End If q.EnableNotification Event:=qevent, ReceiveTimeout:=10000 Exit Sub ErrorHandler: MsgBox "Unexpected error!" + Chr(13) + "Reason: " + Err.Description _ + Chr(13) + "Error: " + Hex(Err.Number) q.EnableNotification Event:=qevent, ReceiveTimeout:=1000 End Sub Private Sub qevent_ArrivedError(ByVal q As Object, ByVal lError As Long, ByVal lCursor As Long) On Error GoTo ErrorHandler If lError = MQ_ERROR_IO_TIMEOUT Then MsgBox "No message arrived during the time-out period." Else MsgBox "An arrived-error event occurred. Error: " + Hex(lError) End If End Exit Sub ErrorHandler: MsgBox "Unexpected error!" + Chr(13) + "Reason: " + Err.Description _ + Chr(13) + "Error: " + Hex(Err.Number) End End Sub