3
\$\begingroup\$

Please review the code below and provide constructive feedback to improve.

Multiple threads call the SendMessageToMSMQ method to send messages to a msmq queue.

Occassionally messageQueue.Send(sendMsg); throws insufficent resources exception. Dont know why it's happening. Storage is not an issue, since I have checked the disk and the queue properties. There is no limit on queue storage. I doubt on the number of msmq connections being opened and closed...

Any help appreciated. Thank you.

     using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{

    /// <summary>
    /// program assumes the msmq private queue with name "queueName" exists
    /// </summary>
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            Parallel.For(0, 10000, index =>
            {
                MSMQSender.SendMessageToMSMQ<msmqMessageObject>(new msmqMessageObject { Name = index.ToString(), Value = index.ToString(), count = index });
            }
            );
        }
    }


    public class MSMQSender
    {
        private static object lockObject = new object();
        private static ConcurrentQueue<msmqMessageObject> concurrentQueue = new ConcurrentQueue<msmqMessageObject>();

        public static void SendMessageToMSMQ<T>(T msmqMessageObject1)
        {
            if (Monitor.TryEnter(lockObject))
            {
                try
                {
                    using (var messageQueue = new MessageQueue())
                    {
                        messageQueue.Path = string.Format(@"Formatname:DIRECT=OS:.\Private$\{0}", "queueName");

                        using (var sendMsg = new Message())
                        {
                            sendMsg.Recoverable = false;
                            sendMsg.Body = msmqMessageObject1;
                            messageQueue.Send(sendMsg);
                        }

                        messageQueue.Close();
                    }

                    if (concurrentQueue.Count > 0)
                    {
                        msmqMessageObject msmqMessageObject2;
                        while (concurrentQueue.TryDequeue(out msmqMessageObject2))
                        {
                            try
                            {
                                using (var messageQueue = new MessageQueue())
                                {
                                    messageQueue.Path = string.Format(@"Formatname:DIRECT=OS:.\Private$\{0}", "queueName");
                                    using (var sendMsg = new Message())
                                    {
                                        sendMsg.Recoverable = false;
                                        sendMsg.Body = msmqMessageObject2;
                                        messageQueue.Send(sendMsg);
                                    }

                                    messageQueue.Close();
                                }
                            }
                            catch (Exception ex)
                            {
                                concurrentQueue.Enqueue(msmqMessageObject1 as msmqMessageObject);
                                if (concurrentQueue.Count > 10)
                                {
                                    //todo: log error
                                }
                                break;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    concurrentQueue.Enqueue(msmqMessageObject1 as msmqMessageObject);
                    if (concurrentQueue.Count > 10)
                    {
                        //todo: log error
                    }
                }
                finally
                {
                    Monitor.Exit(lockObject);
                }
            }
            else
            {
                concurrentQueue.Enqueue(msmqMessageObject1 as msmqMessageObject);
            }
        }
    }

    public class msmqMessageObject
    {
        public string Name;

        public string Value;

        public int count;
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Code Review is a community where programmers peer-review your working code. We require that the code be working correctly, to the best of the author's knowledge, before proceeding with a review. -> Do you have an idea why you get the exception occasionaly? \$\endgroup\$ – dfhwze Jun 14 '19 at 21:39
  • \$\begingroup\$ The code works correctly. Issue is with MSMQ System.Messaging.MessageQueueException Source: System.Messaging Message: Insufficient resources to perform operation. Stack Trace: at System.Messaging.MessageQueue.SendInternal(Object obj, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType) \$\endgroup\$ – Sam Jun 14 '19 at 21:41
  • 1
    \$\begingroup\$ I am sorry, but I don't see how 'correctly working' and 'issue' can be symbiotes. \$\endgroup\$ – dfhwze Jun 14 '19 at 21:48
  • \$\begingroup\$ Created a complete example. \$\endgroup\$ – Sam Jun 15 '19 at 5:08