In this post I covered the basics of setting up a queue and sending a message to it. Here, I’m going to cover the options around receiving that message.
Essentially, there are two possibilities here: you can either set-up an event listener, or you can poll the queue directly, and receive the messages one at a time.
Option 1 - Events
The events option seems to be the one that Microsoft now prefer - essentially, you register a handler and then as the messages come in, you simply handle them inside an event. The code here looks something like this:
var queueClient = new QueueClient(connectionString, "test-queue");
var messageHandlerOptions = new MessageHandlerOptions(ExceptionHandler);
queueClient.RegisterMessageHandler(handleMessage, messageHandlerOptions);
The event handlers:
private static Task ExceptionHandler(ExceptionReceivedEventArgs arg)
{
Console.WriteLine("Something bad happened!");
return Task.CompletedTask;
}
private static Task handleMessage(Message message, CancellationToken cancellation)
{
string messageBody = Encoding.UTF8.GetString(message.Body);
Console.WriteLine("Message received: {0}", messageBody);
return Task.CompletedTask;
}
Option 2 - Polling
With this option, you simply ask for a message. You’ll need to use the approach for things like deferred messages (which I hope to cover in a future post):
var messageReceiver = new MessageReceiver(connectionString, "test-queue", ReceiveMode.ReceiveAndDelete);
var message = await messageReceiver.ReceiveAsync();
string messageBody = Encoding.UTF8.GetString(message.Body);
Console.WriteLine("Message received: {0}", messageBody);
Option 3 - Option 1, but cruelly force it into option 2
I thought I’d include this, although I would strongly advise against using it in most cases. If you wish, you can register an event, but force the event into a procedural call, so that you can await it finishing. You can do this by using the TaskCompletionSource. First, declare a TaskCompletionSource in your code (somewhere accessible):
private static TaskCompletionSource<bool> \_taskCompletionSource;
Then, in handleMessage (see above), when you’ve received the message you want, set the result:
if (message.CorrelationId == correlationId)
{
await client.CompleteAsync(message.SystemProperties.LockToken);
\_taskCompletionSource.SetResult(true);
}
Finally, after you’ve registered the message handler, just await this task:
queueClient.RegisterMessageHandler(
(message, cancellationToken) => handleMessage(correlationId, queueClient, message, cancellationToken),
messageHandlerOptions);
await \_taskCompletionSource.Task;