Azure服务总线接收和删除

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

所以我创建了一个示例应用程序,其中一个应用程序将向队列发送消息并读取消息。对于这个应用程序,我使用“ReceiveAndDelete”,下面是示例代码

创建消息

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
    中的任何基于任务的方法,因此无法获得可预测的输出。