[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

C# MSMQ BeginPeek/PeekCompleted memory leak - Need some help

Posted on 2005-04-13
6
Medium Priority
?
3,299 Views
Last Modified: 2010-06-22
I've got an server app in C# that is basically sitting there waiting for messages to arrive in MSMQ from somewhere else.  I use a BeginPeek( timeout, IASyncResult) call to start the whole process. When the peekCompleted event fires, I disconnect the event handler and then I check to see why it fired. If it's because of a message I deal with the messages. If it is because the timeout expired, I reattach the event handler and call BeginPeek() again.


The problem is that my application is sitting idle, with no messages in the queue and each iteration of BeginPeek/PeekCompleted is leaking object handles. I discovered this by looking at the Task Manager at first. Then by using the .Net Memory Profiler by Sci-Tech. I was able to track down where it was occuring.

Each iteration is leaking 1 Message object and one ManualResetEvent object.

But there can't be any message object because there aren't any messages in the queue! I'm not storing a reference to what EndPeek() returns because I don't care what it is if it's a message my message handling code will take care of it. If its not a message all I need to do is move on and start the 'loop' over again.

Anyone have any idea what's going on or better yet how to fix it? I'm leaking 2 handles every 3 seconds or so and obviously that's a problem. I can post code if need be. It's not really all that complicated what I'm doing which is why it's so confusing and aggravating that it's leaking memory.
0
Comment
Question by:lrwdigital
6 Comments
 
LVL 22

Accepted Solution

by:
cookre earned 400 total points
ID: 13777437
The .NET garbage collector doesn't do anything until memory gets tight.  You might try doing your own periodic GC.Collect() to see if that improves matters.
0
 

Author Comment

by:lrwdigital
ID: 13777641
Unfortunately, even if I do a GC, which I'm pretty loathe to do, it doesn't guarantee that anything will happen since the CRL is what determines when garbage is actually collected.

I can see by the .Net Memory Profiler that stuff IS being collected... and these instances are not. Therefore calling to the GC isn't going to do anything anyway. Additionally calling the GC will slow down the app and create more overhead.

What I need is a way to keep the leak from happening in the first place.
0
 

Author Comment

by:lrwdigital
ID: 13782965
Don't know if this means anything but from looking in the debugger window...

the PeekCompletedEventArgs contains an something called -      [System.Messaging.MessageQueue.AsynchronousRequest]

This class, has as one of the properties of it, a message object. The message object's properties seem to be largely exceptions of SystemInvalidOperationException type though not all of them. Two of them that stand out to me are the onCompletionStatusChanged property ( which contains a System.Threading.IOCompletionCallback) and the resetEvent property ( which contains an ManualResetEvent ). There is also a reference to a Message directly attached to the PeekCompletedEventArgs class through the Message property but it just shows up as an exception of MessageQueueException type.

Oddly enough the IAsyncResult that I get back from the BeginPeek( ) has the same things in it except for no public accessor to the message object that's screwed up. My count of undisposed Message object always goes up on the line of .BeginPeek(). But I don't really know how to force this object to dispose of itself and not hang around. I tried to cast the IAsyncResult as the AsynchronousRequest but the compiler doesn't think it exists ( a non-public class perhaps? ).

the .Net Memory profiler says that these objects root back to System.Threading's IOCompletionCallback. and the the last thing callstack says MessageQueue.ReceiveAsync( ).

Anyone?

Anyone have an idea how to get rid of these extra instances?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:lrwdigital
ID: 13785108
I figured I would test to make sure that it's not some sort of weird remoting voodoo ( since I am remoting in the above app ) and thus wrote a quick test app. All the test app does is attach to a queue ( or create a queue if it doesn't exit ), once set up it calls .BeginPeek() as above. There is additional functionality added to allow me to toss a message into the queue and retreive it but that's all she wrote. Nothing fancy there...

It's basically just...

queue.PeekCompleted+= new PeekCompletedEventHandler( queue_PeekCompleted);
queue.BeginPeek( timeout );

private void queue_PeekCompleted(object sender, PeekCompletedEventArgs e)
{
      try
      {
            Console.Write("Taking a peek...");
            queue.EndPeek( e.AsyncResult );
      }
      catch( MessageQueueException ex )
      {
            if ( ex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout )
            {
                  Console.WriteLine("Peek timeout");
            }
      }
      finally
      {
            if ( ! this.queueShutdown )
                  queue.BeginPeek( PEEK_TIMEOUT, e.AsyncResult.AsyncState );
            else
                  KillQueue( );
      }
}


In the last hour the BeginPeek() has leaked 2,664 message objects and 2,673 ManualResetEvents.
0
 

Expert Comment

by:JJ_
ID: 25140909
Hi lrwdigital,

Did you get a better answer to this? I'm trying to work out if not calling EndPeek is a problem. In your test app in your last post you're not calling EndPeek if there is a timeout. I'm wanting to do something similar - just use BeginPeek as an initiator of an async event, raised in my PeekCompleted event handler. Then something listenting on that event can call-back into my peeking class to get it to call Receive(messageId), then on return from the event raised by my peeking class, at the end of the PeekCompleted function, I do a BeginPeek again. i.e. there's no EndPeek call.

It seems to me that whatever the initial IAsyncReset represents (and whatever it is referencing) may still be haning around... unless the fact that the completion of the execution of the PeekCompleted implements the releasing of the thread (to the thread pool) and dereferences the IAsyncResult stuff. But I'm not certain what happens. Any instights?

Hmmm. Just seen that this is a 2005 question. Hopefully you're still out there and remember what this is all about.

Thanks
0
 
LVL 75

Expert Comment

by:Michel Plungjan
ID: 33045047
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Make the most of your online learning experience.
This article will show how Aten was able to supply easy management and control for Artear's video walls and wide range display configurations of their newsroom.
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
Introduction to Processes

831 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question