How to: Receive Messages Asynchronously 

You can retrieve messages asynchronously in two ways: by using an event handler to receive notification when the operation finishes processing, or by using a callback. For an overview of asynchronous messaging, see Asynchronous Message Processing.

In event notification, you first bind an event handler to the procedure you want to run when the asynchronous call finishes. You then call the BeginReceive method in your code. This starts the asynchronous processing and returns processing to your component when a message becomes available or when the time-out parameter expires. When the call returns, the system runs the delegate you have defined and processes the results of the retrieval. You then call the EndReceive method to indicate the end of the operation.

NoteNote

BeginReceive will retrieve only a single message. If you want to continue processing messages asynchronously, you must either call the BeginReceive method again or use the callback parameter on BeginReceive to call a delegate that will continue to watch for new messages arriving on the queue.

In addition to receiving messages asynchronously, you can peek at messages asynchronously. The pattern for both processes is very similar, except that to peek asynchronously, you use the BeginPeek method.

To create the MessageQueue object programmatically

  1. Add a reference to System.Messaging.dll to your project.

  2. Create an instance of the MessageQueue object in the class you are implementing, and set its Path property (in the constructor) and the Formatter property.

    ' Add this to the constructor
    Dim targetTypeNames() As String = _
       New String() {"System.String,mscorlib"}
    mq.Formatter = _
       New System.Messaging.XmlMessageFormatter(targetTypeNames)
    
    // Add this to the class declarations.
    System.Messaging.MessageQueue mq =
       new System.Messaging.MessageQueue(".\\MyQueue");
    // Add this to the constructor.
    mq.Formatter = new System.Messaging.XmlMessageFormatter(
       new string[] { "System.String,mscorlib" });
    
    // Add this to the class declarations.
    System.Messaging.MessageQueue mq = 
       new System.Messaging.MessageQueue(".\\MyQueue");
    // Add this to the constructor.
    mq.set_Formatter(new System.Messaging.XmlMessageFormatter(
       new String[]{"System.String,mscorlib"}));
    

To create the MessageQueue object in the Designer

  1. Add a reference to System.Messaging.dll to your project.

  2. From the Toolbox, drag a MessageQueue component onto the designer. Set the QueueName property to mq. Set the Formatter property to XmlMessageFormatter. Set the Path property to ".\MyQueue".

To receive a message asynchronously using event notification

  1. Create an event handler for the ReceiveCompleted event. In the designer, double-click the MessageQueue component, and add the code shown below.

    Private Sub mq_ReceiveCompleted(ByVal sender As System.Object, _
    ByVal e As System.Messaging.ReceiveCompletedEventArgs) _
    Handles mq.ReceiveCompleted
        ' Add code here to respond to message.
    End Sub
    
    private void mq_ReceiveCompleted(object sender,
    System.Messaging.ReceiveCompletedEventArgs e)
    {
        // Add code here to respond to message.
    }
    
    // Add this statement to the class constructor.
    mq.add_ReceiveCompleted(
       new    System.Messaging.ReceiveCompletedEventHandler(
          this.mq_ReceiveCompleted));
    private void mq_ReceiveCompleted(System.Object sender, 
       System.Messaging.ReceiveCompletedEventArgs e)
    {
       // Add code here to respond to message.
    }
    
  2. Write code within the event handler to retrieve the message, using the Message object to retrieve the results of the asynchronous call. The following code retrieves the message and displays it on the console.

    Private Sub mq_ReceiveCompleted(ByVal sender As System.Object, _
    ByVal e As System.Messaging.ReceiveCompletedEventArgs) _
    Handles mq.ReceiveCompleted
        Dim m As System.Messaging.Message = mq.EndReceive(e.AsyncResult)
        m.Formatter = New System.Messaging.XmlMessageFormatter( _
           New String() {"System.String,mscorlib"})
        Console.WriteLine("Message: " + m.Body.ToString())
    End Sub
    
    private void mq_ReceiveCompleted(object sender,
    System.Messaging.ReceiveCompletedEventArgs e)
    {
        System.Messaging.Message m = mq.EndReceive(e.AsyncResult);
        m.Formatter = new System.Messaging.XmlMessageFormatter(
           new string[] { "System.String,mscorlib" });
        Console.WriteLine("Message: " + (string)m.Body);
    }
    
    private void mq_ReceiveCompleted(System.Object sender,
        System.Messaging.ReceiveCompletedEventArgs e)
    {
       System.Messaging.Message m = mq.EndReceive(e.get_AsyncResult());
       m.set_Formatter(new System.Messaging.XmlMessageFormatter(
          new String[]{"System.String,mscorlib"}));
       Console.WriteLine(("Message: " + (String)(m.get_Body())));
    }
    
  3. Call the BeginReceive method somewhere in your code to start the asynchronous operation. For example, the following code calls the method when the user clicks a button.

    Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
        mq.BeginReceive()
    End Sub
    
    private void button1_Click(object sender, System.EventArgs e)
    {
        mq.BeginReceive();
    }
    
    private void button1_Click(object sender, System.EventArgs e)
    {
       mq.BeginReceive();
    }
    
  4. If you want to continue receiving messages asynchronously, call the BeginReceive method again in the ReceiveCompleted event handler, shown below. This makes your component continue processing new messages as they are received on the queue.

    Private Sub mq_ReceiveCompleted(ByVal sender As System.Object, _
    ByVal e As System.Messaging.ReceiveCompletedEventArgs) _
    Handles mq.ReceiveCompleted
        Dim m As System.Messaging.Message = mq.EndReceive(e.AsyncResult)
        m.Formatter = New System.Messaging.XmlMessageFormatter( _
           New String() {"System.String,mscorlib"})
        Console.WriteLine("Message: " + m.Body.ToString())
        mq.BeginReceive()
    End Sub
    
    private void mq_ReceiveCompleted(object sender,
    System.Messaging.ReceiveCompletedEventArgs e)
    {
        System.Messaging.Message m = mq.EndReceive(e.AsyncResult);
        m.Formatter = new System.Messaging.XmlMessageFormatter(
           new string[] { "System.String,mscorlib" });
        Console.WriteLine("Message: " + (string)m.Body);
        mq.BeginReceive();
    }
    
    private void mq_ReceiveCompleted(System.Object sender,
       System.Messaging.ReceiveCompletedEventArgs e)
    {
       System.Messaging.Message m = mq.EndReceive(e.get_AsyncResult());
       m.set_Formatter(new System.Messaging.XmlMessageFormatter(
          new System.String[]{"System.String,mscorlib"}));
       Console.WriteLine(("Message: " + (System.String)(m.get_Body())));
       mq.BeginReceive();
    }
    

To receive a message asynchronously using a callback

  1. Create a class that defines information relevant to the message task. In this case, define a Customer class.

    Public Class Customer
        Public Name As String = ""
        Public Sub New(ByVal newName As String)
            Name = newName
        End Sub
    End Class
    
    public class Customer
    {
        public string Name = "";
        public Customer(string name)
        {
            Name = name;
        }
    }
    
  2. Create an instance of the class. This object will be passed to the callback method.

    Dim george As New Customer("George")
    
    Customer george = new Customer("George");
    
  3. Create a callback method according to the AsyncCallback delegate. This method will contain the processing to be done after the message is received. The AsyncState property of the result parameter will contain the object you created to pass information about the message task. In this case, the AsyncState is a Customer object.

    Private Sub ReceiveCallback(ByVal result As System.IAsyncResult)
        Dim buyer As Customer = CType(result.AsyncState, Customer)
        Dim buyerName As String = buyer.Name
    End Sub
    
    private void ReceiveCallback(System.IAsyncResult result)
    {
        Customer buyer = (Customer)result.AsyncState;
        string buyerName = buyer.Name;
    }
    
  4. Call the BeginReceive method somewhere in your code to start the asynchronous operation. For example, the following code calls the method when the user clicks a button. A message is sent to the message queue and then read from the queue. The ReceiveCallback method, defined in step 3 above, is called when the message is received.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles Button1.Click
        MessageQueue1.Send("Buy six eggs.", george.Name)
        MessageQueue1.BeginReceive(New System.TimeSpan(0, 0, 5), george, _
            AddressOf ReceiveCallback)
    End Sub
    
    private void button1_Click(object sender, System.EventArgs e)
    {
        messageQueue1.Send("Buy six eggs.", george.Name);
        messageQueue1.BeginReceive(new System.TimeSpan(0, 0, 5), george,
            new System.AsyncCallback(this.ReceiveCallback));
    }
    

See Also

Tasks

How to: Peek at Messages
How to: Receive Messages Programmatically
How to: Create MessageQueue Component Instances

Concepts

Asynchronous Message Processing

Other Resources

Reading and Receiving Messages