When reading messages asynchronously using ActiveX components, EnableNotification must be called for each message that is read from the queue.
Typically, EnableNotification is called for the first message to be read, and then again in the event handler after you read the arrived message. The subsequent calls to EnableNotification are needed to read the next message in the queue. Notification returns a single Arrived event for each message found in the queue.
The following diagram shows the basic programming model used for reading messages asynchronously. It includes two calls to EnableNotification, plus a call to read the message from the queue.
The model in the diagram shows that there are many ways to combine the two calls to EnableNotification and the call to read the message in the queue. For example, to purge all the messages in a queue you could call EnableNotification with Cursor set to MQMSG_FIRST, call Receive, then call EnableNotification with Cursor set to MQMSG_FIRST.
However, not all combinations necessarily make good programming "sense." For instance, it is possible to write an event handler that would only read every other message in the queue.
The initial call to EnableNotification and the subsequent call from the event handler can tell MSMQ to check if a message is in the queue at all (Cursor = MQMSG_FIRST), if a message is at the current cursor location (Cursor = MQMSG_CURRENT), or if a message is at the next position after the cursor (Cursor = MQMSG_NEXT). The default is to trigger the Arrived event when MSMQ finds any message in the queue (Cursor = MQMSG_FIRST).
The calls to read the message in the queue include: Receive, ReceiveCurrent, Peek, PeekCurrent, or PeekNext.
Note Each call to EnableNotification, plus the calls to ReceiveCurrent, PeekCurrent, or PeekNext, provide numerous ways to navigate through the queue. Each call can affect how the implied cursor is moved through the queue.
Set queue = qInfo.Open(MQ_RECEIVE_ACCESS, MQ_DENY_NONE) queue.EnableNotification Event:=Event, Cursor:=MQMSG_CURRENT, ReceiveTimeout:=1000
Private Sub TheEvent_Arrived(ByVal Queue As Object, ByVal Cursor As Long) Dim msgrec As MSMQMessage On Error GoTo Error_TheEvent_Arrived Set msgrec = queue.PeekCurrent(ReceiveTimeout:=0) If msgrec.AppSpecific = 34 Then Set msgrec = queue.ReceiveCurrent(ReceiveTimeout:=0) MsgBox "Found a message with AppSpecific = 34", vbOKOnly, "Inside the Arrived Event handler" Else queue.EnableNotification TheEvent, MQMSG_NEXT, 1000 End If Exit Sub Error_TheEvent_Arrived: MsgBox Err.Description + " in TheEvent_Arrived sub" End Sub
Private Sub TheEvent_ArrivedError(ByVal Queue As Object, ByVal ErrorCode As Long, ByVal Cursor As Long) MsgBox Err.Description + " in TheEvent_ArrivedError sub" End Sub
This example sends several messages with different application-specific identifiers to a queue, then searches the queue for the message whose application-specific identifier equals 34.
Option Explicit Dim queue As MSMQQueue Dim WithEvents TheEvent As MSMQEvent Private Sub Form_Click() Dim qinfo As New MSMQQueueInfo Dim msgSend As New MSMQMessage Dim i As Integer On Error Resume Next Set TheEvent = New MSMQEvent qInfo.PathName = ".\AsyncSearchDemo" qInfo.Create On Error GoTo Error_Form_Click Set queue = qinfo.Open(MQ_SEND_ACCESS, MQ_DENY_NONE) msgSend.AppSpecific = 24 msgSend.Send queue msgSend.AppSpecific = 34 msgSend.Send queue msgSend.AppSpecific = 44 msgSend.Send queue msgSend.AppSpecific = 54 msgSend.Send queue msgSend.AppSpecific = 64 msgSend.Send queue queue.Close '**************************** '* Open queue and start '* notification. '**************************** Set queue = qinfo.Open(MQ_RECEIVE_ACCESS, MQ_DENY_NONE) queue.EnableNotification Event:=Event, Cursor:=MQMSG_CURRENT, ReceiveTimeout:=1000 Exit Sub Error_Form_Click: MsgBox Err.Description End Sub '**************************** '* Define Arrived event handler. '**************************** Private Sub TheEvent_Arrived(ByVal Queue As Object, ByVal Cursor As Long) Dim msgrec As MSMQMessage On Error GoTo Error_TheEvent_Arrived Set msgrec = queue.PeekCurrent(ReceiveTimeout:=0) If msgrec.AppSpecific = 34 Then Set msgrec = queue.ReceiveCurrent(ReceiveTimeout:=0) MsgBox "Found a message with AppSpecific = 34", vbOKOnly, "Inside the Arrived Event handler" Else queue.EnableNotification TheEvent, MQMSG_NEXT, 1000 End If Exit Sub Error_TheEvent_Arrived: MsgBox Err.Description + " in TheEvent_Arrived sub" End Sub Private Sub TheEvent_ArrivedError(ByVal Queue As Object, ByVal ErrorCode As Long, ByVal Cursor As Long) MsgBox Err.Description + " in TheEvent_ArrivedError sub" End Sub