c# - 从服务总线队列接收消息适用于控制台应用程序,但不适用于 Windows 窗体应用程序?

标签 c# multithreading azure azureservicebus azure-servicebus-queues

我有以下 C# 函数,允许我从 Azure 接收来自给定队列的消息,它在控制台应用程序上运行良好:

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);
        }

我现在的目标是使用列表框控件列出消息。 但是,如果我尝试在单击按钮时调用相同的主要方法,则什么也不会发生,在 Debug模式下,我注意到我的 win 表单应用程序永远不会到达 ProcessMessagesAsync 中的断点。

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]);
        }

我尝试使用以下代码在线程池中对我的任务进行排队,但没有帮助:

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

最佳答案

请按照以下解决方法将服务总线队列消息放入Windows 窗体

将数据显示到 LISTBOX 的三个主要步骤

  1. 使用 ListBox 类提供的 ListBox() 构造函数创建列表框。

     ListBox listBox1 = new ListBox();
    
  2. 设置/添加 ListBox 类提供的 ListBox 的 Items 属性。

     listBox1.Items.Add("your data to add in listbox");
    
  3. 使用 Add() 方法将此 ListBox 控件添加到表单。

     this.Controls.Add(listBox1);
    

这里我按照上述步骤操作。

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

这里我添加一个按钮,如果我们点击该按钮,它将获取服务总线队列消息并将其添加到列表框中。

    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;
            }
        }
    }

您可以按照我提到的上述步骤进行操作。使用这个我可以看到 Windows 窗体中的服务总线队列消息列表

enter image description here

关于c# - 从服务总线队列接收消息适用于控制台应用程序,但不适用于 Windows 窗体应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71002520/

相关文章:

c# - XML 解析在第 1 行第 9 列失败 : DTD is prohibited

ios - prepareForSegue 中出现“从不正确的线程访问的 Realm ”错误; swift

java - Scala 中有趣的线程行为

powershell - Set-WindowsAzureLog 的替代品是什么?

c# - 这是简化继承类的有效方法吗?

c# - C# 中的高级列表比较

c# - 是否可以限制 EventWaitHandle 的设置/重置?

c# - 为什么在显示表单时 TextBox 中的文本会突出显示(选中)?

java - 如何命名线程?

使用 WebGet Web 服务进行 Azure 日志记录