Azure服务总线接收和删除
所以我创建了一个示例应用程序,其中一个应用程序将向队列发送消息并读取消息。对于这个应用程序,我使用“ReceiveAndDelete”,下面是示例代码 创建消息Azure服务总线接收和删除,azure,azureservicebus,azure-servicebus-queues,Azure,Azureservicebus,Azure Servicebus Queues,所以我创建了一个示例应用程序,其中一个应用程序将向队列发送消息并读取消息。对于这个应用程序,我使用“ReceiveAndDelete”,下面是示例代码 创建消息 private static async void CreateMessage(string queueName, string textMessage) { // create a Service Bus client await using (ServiceBusClient client = new Servic
private static async void CreateMessage(string queueName, string textMessage)
{
// create a Service Bus client
await using (ServiceBusClient client = new ServiceBusClient(connectionString))
{
// create a sender for the queue
ServiceBusSender sender = client.CreateSender(queueName);
// create a message that we can send
ServiceBusMessage message = new ServiceBusMessage(textMessage);
// send the message
await sender.SendMessageAsync(message);
Console.WriteLine($"Sent a single message to the queue: {queueName}");
}
}
// handle received messages
static async Task MessageHandler(ProcessMessageEventArgs args)
{
string body = args.Message.Body.ToString();
Console.WriteLine($"Received: {body}");
// complete the message. messages is deleted from the queue.
await args.CompleteMessageAsync(args.Message);
}
// handle any errors when receiving messages
static Task ErrorHandler(ProcessErrorEventArgs args)
{
Console.WriteLine(args.Exception.ToString());
return Task.CompletedTask;
}
static async Task ReceiveMessagesAsync()
{
var processorOptions = new ServiceBusProcessorOptions
{
AutoCompleteMessages = false,
MaxConcurrentCalls = 1,
MaxAutoLockRenewalDuration = TimeSpan.FromMinutes(10),
ReceiveMode = ServiceBusReceiveMode.ReceiveAndDelete,
PrefetchCount = 1
};
await using (ServiceBusClient client = new ServiceBusClient(connectionString))
{
// create a processor that we can use to process the messages
ServiceBusProcessor processor = client.CreateProcessor(queueName, processorOptions);
// add handler to process messages
processor.ProcessMessageAsync += MessageHandler;
// add handler to process any errors
processor.ProcessErrorAsync += ErrorHandler;
// start processing
await processor.StartProcessingAsync();
Console.WriteLine("Wait for a minute and then press any key to end the processing");
Console.ReadKey();
// stop processing
Console.WriteLine("\nStopping the receiver...");
await processor.StopProcessingAsync();
Console.WriteLine("Stopped receiving messages");
}
}
接收信息
private static async void CreateMessage(string queueName, string textMessage)
{
// create a Service Bus client
await using (ServiceBusClient client = new ServiceBusClient(connectionString))
{
// create a sender for the queue
ServiceBusSender sender = client.CreateSender(queueName);
// create a message that we can send
ServiceBusMessage message = new ServiceBusMessage(textMessage);
// send the message
await sender.SendMessageAsync(message);
Console.WriteLine($"Sent a single message to the queue: {queueName}");
}
}
// handle received messages
static async Task MessageHandler(ProcessMessageEventArgs args)
{
string body = args.Message.Body.ToString();
Console.WriteLine($"Received: {body}");
// complete the message. messages is deleted from the queue.
await args.CompleteMessageAsync(args.Message);
}
// handle any errors when receiving messages
static Task ErrorHandler(ProcessErrorEventArgs args)
{
Console.WriteLine(args.Exception.ToString());
return Task.CompletedTask;
}
static async Task ReceiveMessagesAsync()
{
var processorOptions = new ServiceBusProcessorOptions
{
AutoCompleteMessages = false,
MaxConcurrentCalls = 1,
MaxAutoLockRenewalDuration = TimeSpan.FromMinutes(10),
ReceiveMode = ServiceBusReceiveMode.ReceiveAndDelete,
PrefetchCount = 1
};
await using (ServiceBusClient client = new ServiceBusClient(connectionString))
{
// create a processor that we can use to process the messages
ServiceBusProcessor processor = client.CreateProcessor(queueName, processorOptions);
// add handler to process messages
processor.ProcessMessageAsync += MessageHandler;
// add handler to process any errors
processor.ProcessErrorAsync += ErrorHandler;
// start processing
await processor.StartProcessingAsync();
Console.WriteLine("Wait for a minute and then press any key to end the processing");
Console.ReadKey();
// stop processing
Console.WriteLine("\nStopping the receiver...");
await processor.StopProcessingAsync();
Console.WriteLine("Stopped receiving messages");
}
}
主要方法
static string connectionString = "***";
static string queueName = "firstqueue";
static async Task Main(string[] args)
{
try
{
await CreateMessage(queueName, "Message 1 to test 'ReceiveAndDelete'");
await CreateMessage(queueName, "Message 2 to test 'ReceiveAndDelete'");
await ReceiveMessagesAsync();
}
catch (Exception ex)
{
throw;
}
Console.ReadKey();
}
一切都很正常,但只要应用程序调用“wait processor.StartProcessingAsync();”所有消息都将从队列中读取,即使所有消息尚未处理。在我的示例中,队列中有两条消息,但当调用“wait processor.StartProcessingAsync();”时,消息计数变为零(基本上消息已退出队列),它开始逐个处理消息。据我所知,如果消息尚未开始处理,那么它应该在队列中。在本例中,只应从队列中删除一条消息,第二条消息应在队列中可见
是预期的行为还是我遗漏了什么
是预期的行为还是我遗漏了什么
这是ReceiveAndDelete
模式的预期行为。无论客户端是否能够处理消息,服务总线都会在消息发送到客户端后立即删除该消息
由此:
此操作从队列或订阅接收消息,并且
在一个原子中从该队列或订阅中删除消息
手术
如果要控制此行为,可能需要在PeekLock
模式下获取消息,处理该消息,然后在消息上调用Complete
方法以删除该消息(如果处理成功)
更新
我尝试了你的代码,以下是我的观察结果:
PrefetchCount=1
,第一次从队列中提取并删除2条消息。然后,获取并删除一条消息。可能的解释是,1条消息是预取的,1条消息是根据请求提取的
预取计数=0
(或从'processorOptions'中省略),获取并删除单个消息
using System;
using System.Threading.Tasks;
using Azure.Messaging.ServiceBus;
namespace SO67076189
{
class Program
{
static string connectionString = "connection-string";
static string queueName = "queue-name";
static async Task Main(string[] args)
{
try
{
await CreateMessage(queueName, "Message 1 to test 'ReceiveAndDelete'");
await CreateMessage(queueName, "Message 2 to test 'ReceiveAndDelete'");
await CreateMessage(queueName, "Message 3 to test 'ReceiveAndDelete'");
await CreateMessage(queueName, "Message 4 to test 'ReceiveAndDelete'");
await CreateMessage(queueName, "Message 5 to test 'ReceiveAndDelete'");
await ReceiveMessagesAsync();
}
catch (Exception ex)
{
throw;
}
Console.ReadKey();
}
private static async Task CreateMessage(string queueName, string textMessage)
{
// create a Service Bus client
await using (ServiceBusClient client = new ServiceBusClient(connectionString))
{
// create a sender for the queue
ServiceBusSender sender = client.CreateSender(queueName);
// create a message that we can send
ServiceBusMessage message = new ServiceBusMessage(textMessage);
// send the message
await sender.SendMessageAsync(message);
Console.WriteLine($"Sent a single message to the queue: {queueName}");
}
}
static async Task MessageHandler(ProcessMessageEventArgs args)
{
string body = args.Message.Body.ToString();
Console.WriteLine($"Received: {body}");
// complete the message. messages is deleted from the queue.
//await args.CompleteMessageAsync(args.Message);
}
// handle any errors when receiving messages
static Task ErrorHandler(ProcessErrorEventArgs args)
{
Console.WriteLine(args.Exception.ToString());
return Task.CompletedTask;
}
static async Task ReceiveMessagesAsync()
{
var processorOptions = new ServiceBusProcessorOptions
{
//AutoCompleteMessages = false,
//MaxConcurrentCalls = 1,
//MaxAutoLockRenewalDuration = TimeSpan.FromMinutes(10),
ReceiveMode = ServiceBusReceiveMode.ReceiveAndDelete,
//PrefetchCount = 1
};
await using (ServiceBusClient client = new ServiceBusClient(connectionString))
{
// create a processor that we can use to process the messages
ServiceBusProcessor processor = client.CreateProcessor(queueName, processorOptions);
// add handler to process messages
processor.ProcessMessageAsync += MessageHandler;
// add handler to process any errors
processor.ProcessErrorAsync += ErrorHandler;
// start processing
await processor.StartProcessingAsync();
Console.WriteLine("Wait for a minute and then press any key to end the processing");
Console.ReadKey();
// stop processing
Console.WriteLine("\nStopping the receiver...");
await processor.StopProcessingAsync();
Console.WriteLine("Stopped receiving messages");
}
}
}
}
谢谢@Gaurav,我理解它阅读并删除了邮件。但如果有一条以上的信息,为什么它会全部阅读并删除呢。链接没有说它将读取所有消息并从队列中删除所有消息。可能是因为
预取计数=10
?您可以尝试将其更改为1或全部删除吗?有关预回迁计数的详细信息,请参见此处:。@RaviKhambhati在调查问题之前,请先尝试等待您的方法,否则可能会出现问题。@GauravMantri使用预回迁计数=1进行了测试,得到了相同的结果。将代码更新为well@PeterBons按建议更新代码。同样经过测试,得到了相同的结果。您不需要等待Main
中的任何基于任务的方法,因此无法获得可预测的输出。