以下に、Azure Service Bus キューを使用するかなり単純な .NET コンソール アプリを示します。
ご覧のとおり、Task.Factory を使用して 25 個のレシーバー タスクを起動し、APM スタイルの BeginMessageReceive メソッドを呼び出しています。次に、EndMessageReceive の最後で、もう一度 BeginMessageReceive を呼び出してループを続行します。
私の質問は、APM スタイルの BeginMessageReceive/EndMessageReceive から、再帰タスクを使用し、場合によっては C# 5.0 async/await を利用する TPL/TAP アプローチに切り替えて、同じようなことを達成するにはどうすればよいかということです。
using System;
using System.Configuration;
using System.Threading.Tasks;
using Microsoft.ServiceBus.Messaging;
namespace ServiceBusConsumer
{
class Program
{
private static QueueClient _queueClient;
private static void Main(string[] args)
{
var connectionString = ConfigurationManager.AppSettings["Microsoft.ServiceBus.ConnectionString"];
_queueClient = QueueClient.CreateFromConnectionString(connectionString, "MyQueue");
for (var i = 0; i < 25; i++ )
{
Task.Factory.StartNew(BeginMessageReceive);
}
Console.WriteLine("Waiting for messages...");
Console.ReadKey();
_queueClient.Close();
} //end private static void Main(string[] args)
private static void BeginMessageReceive()
{
_queueClient.BeginReceive(TimeSpan.FromMinutes(5), EndMessageReceive, null);
}
private static void EndMessageReceive(IAsyncResult iar)
{
var message = _queueClient.EndReceive(iar);
try
{
if (message != null)
{
var msg = message.GetBody<string>();
Console.WriteLine("Message: " + msg);
if (_queueClient.Mode == ReceiveMode.PeekLock)
{
// Mark brokered message as completed at which point it's removed from the queue.
message.Complete();
}
}
}
catch (Exception ex)
{
if (_queueClient.Mode == ReceiveMode.PeekLock)
{
// unlock the message and make it available
message.Abandon();
}
Console.WriteLine("Exception was thrown: " + ex.GetBaseException().Message);
}
finally
{
if (message != null)
{
message.Dispose();
}
}
BeginMessageReceive();
}
}
}
MessageReceive タイムアウトの期限が切れた場合に再帰的に自分自身を再度呼び出すための新しい変更されたコード:
private static async Task MessageReceiveAsync()
{
while (true)
{
using (var message = await _queueClient.ReceiveAsync(TimeSpan.FromMinutes(5)))try
{
if (message != null)
{
try
{
var msg = message.GetBody<string>();
Console.WriteLine("Message: " + msg);
if (_queueClient.Mode == ReceiveMode.PeekLock)
{
// Mark brokered message as completed at which point it's removed from the queue.
await message.CompleteAsync();
}
}
catch (Exception ex)
{
message.AbandonAsync();
Console.WriteLine("Exception was thrown: " + ex.GetBaseException().Message);
}
}
}
}
}