'Receiving message from Service Bus queue is working on console apps but not in windows form apps?

I have the following c# functions that allow me to receive messages from a given queue from Azure, it works fine on console apps :

public  async Task MainReceiver()
        {
            queueClient = new QueueClient(connectionString, queueName);

            var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = 5,
                AutoComplete = false,

            };

            queueClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);

            Console.ReadLine();

            await queueClient.CloseAsync();
        }

        public  async Task ProcessMessagesAsync(Message message, CancellationToken token)
        {
            var jsonString = Encoding.UTF8.GetString(message.Body);
            Console.WriteLine($"Person Received: { jsonString }");
            List<string> data = new List<string>();

            if (messageLists.ContainsKey(queueName))
            {
                data = messageLists[queueName];
                messageLists.Remove(queueName);
                data.Add(jsonString);
            }
            else
            {
                data.Add(jsonString);
            }
            messageLists.Add(queueName, data);

            await queueClient.CompleteAsync(message.SystemProperties.LockToken);
        }

My goal now is to list the messages using a listbox control. But if i try to call the same main methode in a button click, nothing happends, in debug mode i noticed that my breakpoint in ProcessMessagesAsync is never reached by my win form app.

public async void button2_Click(object sender, EventArgs e)
        {
            await receiveMessage();
        }
public async Task receiveMessage()
        {
            await messages.MainReceiver();
            List<string> data = new List<string>();
            data = messages.messageLists["eventsqueue"];
            for (int i = 0; i < messages.messageLists.Count; i++)
                listBox1.Items.Add(data[i]);
        }

I tried to use to queue my task in the thread pool using the following code , but it didn't help :

ThreadPool.QueueUserWorkItem(async (w) => await messages.MainReceiver());


Solution 1:[1]

Please follow the below workaround to achieve Service Bus queue messages into Windows Forms

Three major steps to show your data into LISTBOX

  1. Create a list box using the ListBox() constructor is provided by the ListBox class.

     ListBox listBox1 = new ListBox();
    
  2. Set/Add the Items property of the ListBox provided by the ListBox class.

     listBox1.Items.Add("your data to add in listbox");
    
  3. Add this ListBox control to the form using Add() method.

     this.Controls.Add(listBox1);
    

Here I am following the above steps.

Program.cs

    using System.Collections.Generic;
    using System.Windows.Forms;
    
    namespace servicebuswinform
    {
        using Microsoft.Azure.ServiceBus;
        using System;
        using System.Text;
        using System.Threading;
        using System.Threading.Tasks;
        public class Program
        {
            const string ServiceBusConnectionString = <ServiceBus Connection string>;
            const string QueueName = "<Queue name>";
            static IQueueClient queueClient;
            public static List<string> data = new List<string>();
    
            [STAThread]
        
            public static void Main()
            {
                Application.SetHighDpiMode(HighDpiMode.SystemAware);
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        
            public static async Task MainAsync()
            {
                const int numberOfMessages = 10;
                queueClient = new QueueClient(ServiceBusConnectionString, QueueName);
                RegisterOnMessageHandlerAndReceiveMessages();
                // Send Messages
                await SendMessagesAsync(numberOfMessages);
                await queueClient.CloseAsync();
            }
        
            public static void RegisterOnMessageHandlerAndReceiveMessages()
            {
                var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
                {
                    MaxConcurrentCalls = 1,
                    AutoComplete = false
                };
                // Register the function that will process messages
                queueClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
            }
        
            public static async Task ProcessMessagesAsync(Message message, CancellationToken token)
            {
                //Adding message into list
                data.Add("Received message: SequenceNumber:"+ message.SystemProperties.SequenceNumber.ToString()+" Body:" + Encoding.UTF8.GetString(message.Body));
                await queueClient.CompleteAsync(message.SystemProperties.LockToken);
            }
        
        // Use this Handler to look at the exceptions received on the MessagePump
        
            public static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
            {
                Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
                var context = exceptionReceivedEventArgs.ExceptionReceivedContext;
                Console.WriteLine("Exception context for troubleshooting:");
                Console.WriteLine($"- Endpoint: {context.Endpoint}");
                Console.WriteLine($"- Entity Path: {context.EntityPath}");
                Console.WriteLine($"- Executing Action: {context.Action}");
                return Task.CompletedTask;
            }
    
            public static async Task SendMessagesAsync(int numberOfMessagesToSend)
            {
                try
                {
                for (var i = 0; i < numberOfMessagesToSend; i++)
                    {
                        // Create a new message to send to the queue
                        string messageBody = $"Message {i}";
                        var message = new Message(Encoding.UTF8.GetBytes(messageBody));
                        // Write the body of the message to the console
                        Console.WriteLine($"Sending message: {messageBody}");
                        // Send the message to the queue
                        await queueClient.SendAsync(message);
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
                }
            }
        }
    }

Form.cs

Here I am adding one button if we hit the button it will get the service bus queue messages and it will be added in Listbox.

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    namespace servicebuswinform
    {
        public partial class Form1 : Form
        {
            public static List<string> data1 = new List<string>();
            public Form1()
            {
                InitializeComponent();
            }
            
            public async void button1_Click(object sender, EventArgs e)
            {
                await receiveMessage();
                ListBox listBox1 = new ListBox();
                this.listBox1.Visible = true;
                for (int i = 0; i < data1.Count; i++)
                {
                    listBox1.FormattingEnabled = true;
                    listBox1.Enabled = true;
                    listBox1.Size = new System.Drawing.Size(692, 214);
                    listBox1.Location = new System.Drawing.Point(1, 131);
                    listBox1.MultiColumn = true;
                    listBox1.SelectionMode = SelectionMode.MultiExtended;
                    listBox1.BeginUpdate();
                    listBox1.Items.Add("item" + data1[i].ToString());
                }
                this.Controls.Add(listBox1);
            }
            
            public static async Task receiveMessage()
            {
                await Program.MainAsync();
                data1 = Program.data;
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                this.listBox1.Visible = false;
            }
        }
    }

You can follow the above steps which I have mentioned. Using this I can see the list of service bus queue messages in windows forms

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 DelliganeshS-MT