MSMQ message processing in a Windows service

I have a windows service for processing msmq messages. He relies on the following logic

. There is a timer in the Windows service. Every ten minutes, he will execute a method called "ProcessMessages".

. Inside this method, it first creates a list of existing MessageIds by calling the GetAllMessages method on the queue.

. For each messageId, it receives a message (using ReceiveById) and saves it to a file

Is there a better way to achieve message processing?

Link: http://www.switchonthecode.com/tutorials/creating-a-simple-windows-service-in-csharp

Note. The following code does not give the desired result when I did it as a service; however, there is no error in the event viewer (I do not make any explicit protocols). It worked great when it was a simple console application. How to fix it? [Now it works when I replaced accoun with "User" as shwon in the comments below]

My requirements for action are to process all messages in fixed time intervals - say, only at 10 am and 11 am (every day). What is the best approach for this?

namespace ConsoleSwitchApp { class Program : ServiceBase { private static Timer scheduleTimer = null; static MessageQueue helpRequestQueue = null; static System.Messaging.XmlMessageFormatter stringFormatter = null; static void Main(string[] args) { ServiceBase.Run(new Program()); } public Program() { this.ServiceName = "LijosService6"; //Queue initialize helpRequestQueue = new MessageQueue(@".\Private$\MyPrivateQueue", false); stringFormatter = new System.Messaging.XmlMessageFormatter(new string[] { "System.String" }); //Set Message Filters MessagePropertyFilter filter = new MessagePropertyFilter(); filter.ClearAll(); filter.Body = true; filter.Label = true; filter.Priority = true; filter.Id = true; helpRequestQueue.MessageReadPropertyFilter = filter; //Start a timer scheduleTimer = new Timer(); scheduleTimer.Enabled = true; scheduleTimer.Interval = 120000;//2 mins scheduleTimer.AutoReset = true; scheduleTimer.Start(); scheduleTimer.Elapsed += new ElapsedEventHandler(scheduleTimer_Elapsed); } protected static void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e) { ProcessMessages(); } private static void ProcessMessages() { string messageString = "1"; //Message Processing List<string> messageIdList = GetAllMessageId(); foreach (string messageId in messageIdList) { System.Messaging.Message messages = helpRequestQueue.ReceiveById(messageId); //Store the message into database messages.Formatter = stringFormatter; string messageBody = System.Convert.ToString(messages.Body); if (String.IsNullOrEmpty(messageString)) { messageString = messageBody; } else { messageString = messageString + "___________" + messageBody; } } //Write File string lines = DateTime.Now.ToString(); lines = lines.Replace("/", "-"); lines = lines.Replace(":", "_"); System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\test" + lines + ".txt"); file.WriteLine(messageString); file.Close(); } private static List<string> GetAllMessageId() { List<string> messageIdList = new List<string>(); DataTable messageTable = new DataTable(); messageTable.Columns.Add("Label"); messageTable.Columns.Add("Body"); //Get All Messages System.Messaging.Message[] messages = helpRequestQueue.GetAllMessages(); for (int index = 0; index < messages.Length; index++) { string messageId = (System.Convert.ToString(messages[index].Id)); messageIdList.Add(messageId); messages[index].Formatter = stringFormatter; messageTable.Rows.Add(new string[] { messages[index].Label, messages[index].Body.ToString() }); } return messageIdList; } protected override void OnStart(string[] args) { base.OnStart(args); } protected override void OnStop() { base.OnStop(); } } } namespace ConsoleSwitchApp { [RunInstaller(true)] public class MyWindowsServiceInstaller : Installer { public MyWindowsServiceInstaller() { var processInstaller = new ServiceProcessInstaller(); var serviceInstaller = new ServiceInstaller(); //set the privileges processInstaller.Account = ServiceAccount.LocalSystem; serviceInstaller.DisplayName = "LijosService6"; serviceInstaller.StartType = ServiceStartMode.Manual; //must be the same as what was set in Program constructor serviceInstaller.ServiceName = "LijosService6"; this.Installers.Add(processInstaller); this.Installers.Add(serviceInstaller); } } } 
+7
source share
2 answers

A good alternative to using a timer is to use the MessageQueue.BeginReceive method and work in the ReceiveCompleted event. This way, your code will wait until a message appears in the queue, and then immediately process the message, and then check the following message.

Short stub (full example in a related MSDN article.)

 private void Start() { MessageQueue myQueue = new MessageQueue(".\\myQueue"); myQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(MyReceiveCompleted); myQueue.BeginReceive(); } private static void MyReceiveCompleted(Object source, ReceiveCompletedEventArgs asyncResult) { try { MessageQueue mq = (MessageQueue)source; Message m = mq.EndReceive(asyncResult.AsyncResult); // TODO: Process the m message here // Restart the asynchronous receive operation. mq.BeginReceive(); } catch(MessageQueueException) { // Handle sources of MessageQueueException. } return; } 
+14
source

Why not sign up for the ReceiveCompleted event? Alternatively, if both the senders and the subscriber are .Net projects that you are working on, use WCF on MSMQ .

+2
source

All Articles