OutOfMemoryException

Oct 12, 2010 at 5:10 PM

Hi,

first of all, thank you for sharing this nice dll.

Now I have a problem when I loop through a mailbox to clean it up (sort of "DeleteAll"). I keep getting OutOfMemoryExceptions. At first it happened around +- 100 mails read and deleted. I went through the source code and added some Dispose() calls for Stream, Reader and AsynchronousSendContext instances (IDisposables). Seems slightly better since it now reaches to somewhere between 200 and 300 messages read and deleted. I dispose and recreate the Pop3Client instance after every 50 mails now. Still memoryproblems, not from the same method per se by the way. Could this be a C#Mail problem or is it more likely that I'm missing something (obvious?)?

Thanx in advance.

 

Kind regards Mario

Coordinator
Oct 12, 2010 at 5:18 PM

Memory problem is quiet difficult to detect the reason without code.
Please show me the entire reproduction code.

Oct 12, 2010 at 5:28 PM

This is the mainpart, apart from some helper and init functions. No streams or readers there. The errors come from "inside the C#Mail" code.

 

private static Pop3Client setClient()
        {
            Pop3Client cl = new Pop3Client();
            cl.UserName = "XXXXXXXXXXXXXXXXX";
            cl.Password = "XXXXXXX";
            cl.ServerName = "XXXXXXXXXXXXXXX";
            cl.AuthenticateMode = Pop3AuthenticateMode.Auto;
            cl.Ssl = false;
            cl.Port = 110;
            cl.ReceiveTimeout = 60000;
            cl.Authenticate();
            nofmessages = cl.GetTotalMessageCount();
            return cl;
        }

        private static void CleanUpRounds(Pop3Client cl)
        {
            //reset counter
            if (c > 0)
            {
                rounds++;
                cl.ExecuteQuit();
                cl.Close();
                cl.Dispose();

                c = 0;
                Thread.Sleep(1000);

                //setClient();
                Console.WriteLine(rounds);
                CleanUp(setClient());
            }
            else if (rounds == 1 && cl == null)
            {
                //setClient();
                Console.WriteLine(rounds);
                CleanUp(setClient());
            }
            
        }

        private static Int32 max = 50;
        private static Int32 c = 0;
        private static Int32 rounds = 1;
        private static void CleanUp(Pop3Client cl)
        {
            count = cl.GetTotalMessageCount();
            if (c <= max && count > 0)
            {
                try
                {
                    Console.WriteLine("nofmessages count: " + count);

                    //Get last mail out of mailbox
                    Pop3Message pm = cl.GetMessage(count);

                    Int32 bounce = CheckMessage(pm.BodyText);
                    if (bounce == 2)
                    {
                        DeactivateHardBounce(pm.BodyText);
                    }
                    else if (bounce == 1)
                    {
                        nofwarnings++;
                        //notify WebMaster of non-critical bounce
                        MailWebMaster(pm.BodyText);
                    }
                    cl.DeleteEMail(count);
                    c++;
                    CleanUp(cl);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
            else
            {
                CleanUpRounds(cl);
            }
        }

Is this sufficient or do you need a full version which you can run on a testmailbox? Or...?

Oct 13, 2010 at 2:55 PM

Changing to a normal for loop with a global Pop3Client instance instead of a recursive function with Pop3Client instance as a parameter seems to have fixed the problem. Not 100% sure about bigger batches, but 300+ messages were handled without a problem. With the recursive version it broke around 150 messages each time. Hope I didn't bother you. Thanks for the quick response anyway.

FYI the errors:

Higuchi.Net.Pop3.Pop3ReceiveException: Exception of type 'System.OutOfMemoryExce
ption' was thrown. ---> System.OutOfMemoryException: Exception of type 'System.O
utOfMemoryException' was thrown.
   at Higuchi.Net.Pop3.Pop3Client.GetResponse(Stream stream, Boolean isMultiLine
)
   at Higuchi.Net.Pop3.Pop3Client.GetResponse(Boolean isMultiLine)
   at Higuchi.Net.Pop3.Pop3Client.Execute(String command, Boolean isMultiLine)
   at Higuchi.Net.Pop3.Pop3Client.Execute(Pop3Command command)
   at Higuchi.Net.Pop3.Pop3Client.GetMessage(Int64 mailIndex)
   --- End of inner exception stack trace ---
   at Higuchi.Net.Pop3.Pop3Client.GetMessage(Int64 mailIndex)
   at BouncedMailCleaner.Program.CleanUp(Pop3Client cl)


OR

Higuchi.Net.Pop3.Pop3ReceiveException: Exception of type 'System.OutOfMemoryExce
ption' was thrown. ---> System.OutOfMemoryException: Exception of type 'System.O
utOfMemoryException' was thrown.
   at System.String.GetStringForStringBuilder(String value, Int32 startIndex, In
t32 length, Int32 capacity)
   at System.Text.StringBuilder.GetNewString(String currentString, Int32 require
dLength)
   at System.Text.StringBuilder.Append(String value)
   at Higuchi.Net.MimeContent.ParseToContentTextList(String text, String multiPa
rtBoundary)
   at Higuchi.Net.Pop3.Pop3Message.Initialize(String text)
   at Higuchi.Net.Pop3.Pop3Message..ctor(String text, Int64 index)
   at Higuchi.Net.Pop3.Pop3Client.GetMessage(Int64 mailIndex)
   --- End of inner exception stack trace ---
   at Higuchi.Net.Pop3.Pop3Client.GetMessage(Int64 mailIndex)
   at BouncedMailCleaner.Program.CleanUp(Pop3Client cl)
totalcount: 153

Coordinator
Oct 15, 2010 at 2:51 PM

Perhaps it was caused by recursive method call.
Set c = 1000 and call CleanUpRounds the stack trace is like this.
CleanUpRounds
-->CleanUp
-->CleanUp
-->CleanUp
...continue
It cause that the memory on stack never released untill clean up finished.
And all object on heap memory include local variable also is not release because the call stack is executing.
The Pop3Message object sometimes large(10MB or more) especialy having attachment file.
As a result,the OutOfMemoryException was thrown.
So,your change not to use recursive call is a correct modification I guess.