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, and call EnableNotification with Cursor set to MQMSG_FIRST.
However, not all combinations necessarily make good programming sense. For example, 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, and 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