title: MSMQ - sending messages to transactional queue became very slow
body: <p>We have an intranet ASP.NET web forms application which performs the actual work via service layer, represented by .NET Remoting services. A couple of weeks ago we've started to get timeout exceptions from IIS, it turned to be that the request from front end was not processed in allowed default execution time (for .NET 2.0+ it is 110sec). During investigation we've found out, that the problem has to be with sending messages to the to the transactional MSMQ queue (runs on W2K3 x64 server). The way we send the messages is the following: from DB we're getting all the records we want to push to the queue and then every single record pushed in separated MSMQ transaction in <b>foreach</b> cycle like this:</p>
  
  <pre><code>using (MessageQueue queue = new MessageQueue(@".\private$\OurQueue"))
  {
    using (MessageQueueTransaction tran = new MessageQueueTransaction())
    {
      tran.Begin();
      Message msg = new Message(BODY); // BODY is some class which holds few fields of type Guid, String and DateTime 
      msg.Label = "Some label for the message";
      msg.UseDeadLetterQueue = true;
      msg.TimeToBeReceived = new TimeSpan(7, 0, 0, 0);
      msg.Priority = MessagePriority.Normal;
      queue.Send(msg, tran);
      tran.Commit();
      queue.Close();
  
      return msg.Id;
    }
  }
  </code></pre>
  
  <p>The number of messages to be sent can reach 30.000-100.000, that's why the performance is crucial.
  Experiments with <b>Stopwatch</b> class have revealed that if you try to change the logic and send all messages in ONE transaction like this:</p>
  
  <pre><code>using (MessageQueue queue = new MessageQueue(@".\private$\OurQueue"))
  {
      using (MessageQueueTransaction tran = new MessageQueueTransaction())
      {
          tran.Begin();
          for (int i = 0; i &lt; recordsNumber; i++)
          {
              Message msg = new Message(BODY); // BODY is some class which holds few fields of type Guid, String and DateTime 
              msg.Label = "Some label for the message";
              msg.UseDeadLetterQueue = true;
              msg.TimeToBeReceived = new TimeSpan(7, 0, 0, 0);
              msg.Priority = MessagePriority.Normal;
              queue.Send(msg, tran);
          }
          tran.Commit();
          queue.Close();
      }
  }
  </code></pre>
  
  <p>the performance is much better - for separated transactions time required to push 30K of records to the MSMQ is ~115 sec, while for 1 transaction it is only ~16 sec. Now this is all guessing to some extend since the profiling and performance estimation was done on my development machine - I don't have access to the production servers, but still this makes me think: <b>is this a correct comparison and if it's a good idea to send several tens of thousands of records to the MSMQ in 1 transaction?</b> However the main question for which I'm still looking for answer is <b>how it happened, that it worked like this for last 7 years or so with separated MSMQ transactions and never timed out, but recently all of a sudden became so slow?</b> Except moving from .NET 3.5 to 4.0 (not to 4.5 unfortunately as we're still using old W2K3 servers) we didn't change anything in the code and farm admin claims there were no changes recently done to the servers themselves (DB x 1, service with Remoting x 2, front end x 2). Profiling on my dev machine has shown that the most work appears to be done in <b>queue.Send</b>, but it shouldn't cause the code to time out, since the call to <b>Send</b> is asynchronous by design, i.e. it should immediately return to the caller (as it's pointed out in <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms711381%28v=vs.85%29.aspx" rel="nofollow" title="documentation">documentation</a>). The code which sends messages to the MSMQ is run inside "main" unit of work, which is DB transaction, but I doubt that the MSMQ transaction got promoted to the MSDTC - I guess in that case it would be always slow.  </p>
  
  <p>Does anybody know what I could miss here?</p>