Using Message Queues In C#

Introduction

 
In today’s article we will look at message queues in C#. We will see what message queues are, why they are important, how to enable standard message queues in Windows 10, and how to create a simple message queue application in C#

What are Message Queues

 
These days we see many business scenarios where large amounts of data must be processed. If we do this in a synchronous or online manner, the whole process will be awfully slow and the application sending the data for processing would have to wait for the response to be received. Similarly, the application processing the data would be overloaded if many requests came in at the same time for processing. The solution to this problem is to use a mechanism that allows for requests to be stored or queued and then the processing or receiving application can pick up these requests one by one and process them. This process is called message queueing. What we do is send a message to the queue which keeps it until it is read by the same or another application. This gives us an offline experience where we can queue as many messages as we like and then these can be processed as required. The two applications, one loading the queue and the other one processing the queue could be on separate machines or processes.
 

Enabling MSMQ to implement messaging on Windows 10

 
The Microsoft implementation of Message Queues is MSMQ (Microsoft Message Queuing). We will now see how to turn on this feature on a Windows 10 machine. In order to use the Message Queuing mechanism, it must be turned on first. We can then create queues and use them in our application.
 
Open Control Panel
 
Using Message Queues In C# 

Next, select Programs
 
Using Message Queues In C# 

Next, select “Turn Windows features on or off”. You would need administrator privileges for this.
 
Using Message Queues In C# 
 
Select, Microsoft Message Queue server and click “ok”
 
Using Message Queues In C# 

Once the feature is installed, you will see the above screen.

Next, we confirm if MSMQ was installed. Open “Computer Management” as below,
 
Using Message Queues In C# 

Let us create a private queue called “empSalary” as below. Right click on Private Queues and select to create a new queue,
 
Using Message Queues In C# 

The private queue is now created.

In the next section, we will use this queue in a simple C# windows application.
 

Simple Application to use Message Queues

 
We have now installed MSMQ and created a private queue. Let us now create a Windows Forms application using Visual Studio 2019 community edition. We will create a simple application to write and read from this queue.
 
Using Message Queues In C#
 
Using Message Queues In C#
 
Using Message Queues In C# 
 
We now add the “System.Messaging” to the references as below,
 
Using Message Queues In C# 
 
Add the code as below,
 
Using Message Queues In C# 
 
Form1.cs
  1. using System;  
  2. using System.Messaging;  
  3. using System.Windows.Forms;  
  4. namespace MsmqTest {  
  5.     public partial class Form1: Form {  
  6.         public Form1() {  
  7.             Initialize Component();  
  8.         }  
  9.         private void Form1_Load(object sender, EventArgs e) {}  
  10.         private void btnLoad Queue_Click(object sender, EventArgs e) {  
  11.             var emp = newEmployee() {  
  12.                 Id = 100, Name = "John Doe", Hours = 55, Rate = 21.0  
  13.             };  
  14.             System.Messaging.Message msg = newSystem.Messaging.Message();  
  15.             msg.Body = emp;  
  16.             MessageQueue msgQ = new MessageQueue(".\\Private$\\empSalary");  
  17.             msgQ.Send(msg);  
  18.         }  
  19.         private void btnRead Queue_Click(object sender, EventArgs e) {  
  20.             MessageQueue msgQ = new MessageQueue(".\\Private$\\empSalary");  
  21.             var emp = new Employee();  
  22.             Object o = newObject();  
  23.             System.Type[] arrTypes = newSystem.Type[2];  
  24.             arr Types[0] = emp.GetType();  
  25.             arr Types[1] = o.GetType();  
  26.             msgQ.Formatter = new XmlMessageFormatter(arrTypes);  
  27.             emp = ((Employee) msgQ.Receive().Body);  
  28.             lblDetails.Text = $ "Employee name: {emp.Name} Salary: {emp.Hours * emp.Rate}";  
  29.         }  
  30.     }  
  31.     public class Employee {  
  32.         public int Id;  
  33.         public string Name;  
  34.         public int Hours;  
  35.         public double Rate;  
  36.     }  
  37. }  
Form1.Designer.cs
  1. namespace MsmqTest {  
  2.     partial class Form1 {  
  3.         ///<summary>  
  4.         /// Required designer variable.  
  5.         ///</summary>  
  6.         private System.ComponentModel.IContainer components = null;  
  7.         ///<summary>  
  8.         /// Clean up any resources being used.  
  9.         ///</summary>  
  10.         ///<param name="disposing">true if managed resources should be disposed; otherwise, false.</param>  
  11.         protected override void Dispose(bool disposing) {  
  12.             if (disposing && (components != null)) {  
  13.                 components.Dispose();  
  14.             }  
  15.             base.Dispose(disposing);  
  16.         }  
  17.         #region Windows Form Designer generated code  
  18.         ///<summary>  
  19.         /// Required method for Designer support - do not modify  
  20.         /// the contents of this method with the code editor.  
  21.         ///</summary>  
  22.         private void InitializeComponent() {  
  23.             this.btnLoadQueue = newSystem.Windows.Forms.Button();  
  24.             this.btnReadQueue = newSystem.Windows.Forms.Button();  
  25.             this.lblDetails = newSystem.Windows.Forms.Label();  
  26.             this.SuspendLayout();  
  27.             //   
  28.             // btnLoadQueue  
  29.             //   
  30.             this.btnLoadQueue.Location = newSystem.Drawing.Point(135, 61);  
  31.             this.btnLoadQueue.Name = "btnLoadQueue";  
  32.             this.btnLoadQueue.Size = newSystem.Drawing.Size(240, 33);  
  33.             this.btnLoadQueue.TabIndex = 0;  
  34.             this.btnLoadQueue.Text = "Load Queue";  
  35.             this.btnLoadQueue.UseVisualStyleBackColor = true;  
  36.             this.btnLoadQueue.Click += newSystem.EventHandler(this.btnLoadQueue_Click);  
  37.             //   
  38.             // btnReadQueue  
  39.             //   
  40.             this.btnReadQueue.Location = newSystem.Drawing.Point(135, 159);  
  41.             this.btnReadQueue.Name = "btnReadQueue";  
  42.             this.btnReadQueue.Size = newSystem.Drawing.Size(240, 31);  
  43.             this.btnReadQueue.TabIndex = 1;  
  44.             this.btnReadQueue.Text = "Read Queue";  
  45.             this.btnReadQueue.UseVisualStyleBackColor = true;  
  46.             this.btnReadQueue.Click += newSystem.EventHandler(this.btnReadQueue_Click);  
  47.             //   
  48.             // lblDetails  
  49.             //   
  50.             this.lblDetails.AutoSize = true;  
  51.             this.lblDetails.Location = newSystem.Drawing.Point(135, 256);  
  52.             this.lblDetails.Name = "lblDetails";  
  53.             this.lblDetails.Size = newSystem.Drawing.Size(0, 13);  
  54.             this.lblDetails.TabIndex = 2;  
  55.             //   
  56.             // Form1  
  57.             //   
  58.             this.AutoScaleDimensions = newSystem.Drawing.SizeF(6 F, 13 F);  
  59.             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;  
  60.             this.ClientSize = newSystem.Drawing.Size(800, 450);  
  61.             this.Controls.Add(this.lblDetails);  
  62.             this.Controls.Add(this.btnReadQueue);  
  63.             this.Controls.Add(this.btnLoadQueue);  
  64.             this.Name = "Form1";  
  65.             this.Text = "Form1";  
  66.             this.Load += newSystem.EventHandler(this.Form1_Load);  
  67.             this.ResumeLayout(false);  
  68.             this.PerformLayout();  
  69.         }  
  70.         #endregion  
  71.         private System.Windows.Forms.ButtonbtnLoadQueue;  
  72.         private System.Windows.Forms.ButtonbtnReadQueue;  
  73.         private System.Windows.Forms.LabellblDetails;  
  74.     }  
  75. }  
This is a simple application in which, on the “Load Queue” button we create an employee class object and write it to the “empSalary” queue. Then, when we click the “Read Queue” button, we read the object and display the calculated salary in a label. In a real-life application, the two functions to load the queue and read from the queue would probably be in separate applications. However, for simplicity purposes I have created both functions in the same application.
 
When, we click “Load Queue”, an instance of the employee class is created and put onto the queue. We can see this as below,
 
Using Message Queues In C# 
 
Once, we click the “Read Queue” button, this object or message is read from the queue and processed and is no longer visible in the queue as below,
 
Using Message Queues In C# 
 
Also, we see the result on the screen,
 
Using Message Queues In C# 
 

Summary

 
In this article, we looked at Message Queues, what they are and why they are important. Next, we saw how to enable Message Queues server on Windows 10. A similar process will be used for enabling it on other Microsoft operating systems. We then created a private message queue and finally created a simple Windows Forms application in C# to first write a message to this queue and then read the message from the queue. The example was simple with both the loading and reading being done from the same screen. However, in a real-life scenario the two functions can be done from separate applications residing on different servers and running in different processes. Hence, this is not only a way to process data in an offline mode but also connect applications across boundaries. Happy Coding!