0

In this example. When I run this in the console, I dont get anything in MyList property so nothing is displayed on the screen. BUT, if I add a breakpoint, I do get the expected content in the list. Possibly because the method where MyList is populated is an async.. and the process of adding to list is a sync? How would you change this code so that MyList is always populated when Program runs?

namespace ReceiverApp
{

    static class Program
    {
        public static List<string> MyList { get; set; }

        const string ServiceBusConnectionString = "Endpoint=sb://...";
        const string QueueName = "...";
        static IQueueClient queueClient;

        static void Main(string[] args)
        {
            MyList = new List<string>();
            MainAsync().GetAwaiter().GetResult();

            foreach (var item in MyList)
            {
                Console.WriteLine(item);
            }
        }

        static async Task MainAsync()
        {
            
            queueClient = new QueueClient(ServiceBusConnectionString, QueueName);

            RegisterOnMessageHandlerAndReceiveMessages();

            await queueClient.CloseAsync();
        }

        static void RegisterOnMessageHandlerAndReceiveMessages()
        {
            var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = 1,

                AutoComplete = false
            };

            queueClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
        }

        static async Task ProcessMessagesAsync(Message message, CancellationToken token)
        {
            // Process the message
            MyList.Add(Encoding.UTF8.GetString(message.Body));
            //await queueClient.CompleteAsync(message.SystemProperties.LockToken);
        }

        static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs args)
        {
            Console.WriteLine($"Message handler encountered an exception {args.Exception}.");
            return Task.CompletedTask;
        }
    }
}
Sami
  • 393
  • 8
  • 22
  • 2
    Your issue is not in the code you've supplied. Specifically, how `ProcessMessagesAsync` is being called is a mystery along with its relationship to `CloseAsync`. Also (and not your issue), if you find yourself calling `Wait`, `Result` or `GetAwaiter().GetResult()` you can be pretty much assured there is a better approach, which is usually rectified by calling `await` – TheGeneral Sep 20 '20 at 23:31
  • 3
    My gut feeling is you are waiting for a response from a message bus which is independent of closing or awaiting `CloseAsync`. – TheGeneral Sep 20 '20 at 23:39
  • 1
    Your code isn't thread-safe - you are (likely) adding to the list from one thread and reading it from another. I'd suggest a `BlockingCollection` would make more sense. – mjwills Sep 21 '20 at 01:31

1 Answers1

0

You're mixing a code that is intended for a continuous message recieving with a short lived and immediately ending console application. If you set a delay after you invoke the registration of the handler, you'll see the messages populated. But this is a wrong implementation. If you want a controlled way to receive messages, you shouldn't use message handler but a message receiver.

Also, closing a queue client will terminate the connection with the broker and prevent message recieving.

Sean Feldman
  • 23,443
  • 7
  • 55
  • 80