I hope that this the appropriate newsgroup for this
posting.
I have a problem with a C# program that accesses eventlogs
on various servers (read only) at our site. The program
is in a continuous loop, so eventually will use up all
available memory before crashing.
I have condensed the code down to a snippet that I have
included below.
While running, the CLR allocates memory for the
eventlogentries, but never seems to release the memory.
GC never collects the memory, even if I call it
explicitly. I even tried calling the close and dispose
methods of the eventlog class, and setting the pointer to
null.
Using a memory profiler, I can see the following:
- The instances are from System.Diagnostics
- The instance names are EventLogEntry
- The allocation stack is:
- Class1.ProcessServerLog()
- EventLogCollection.get_Item()
- EventLog.GetEntryAt()
- EventLog.GetEntryWithOldest()
Am I programmatically forgetting to do something to
release these entries? Or is there some sort of memory
leak in the EventLog class that is not releasing memory
allocated for the entry records?
Thanks for any and all help.
Bryan Hunt
=========================================================
using System;
using System.Diagnostics;
using System.Threading;
namespace Test_Event_Log_Read___Console
{
// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
Class1 myClass1 = new Class1();
while (true)
{
myClass1.ProcessServerLog
("Development","Application");
myClass1.ProcessServerLog("Development", "DNS
Server");
myClass1.ProcessServerLog
("Development", "Security");
myClass1.ProcessServerLog
("Development", "System");
myClass1.ProcessServerLog
("ntwks", "Application");
myClass1.ProcessServerLog
("ntwks", "security");
myClass1.ProcessServerLog
("ntwks", "system");
myClass1.ProcessServerLog
("w2kserver", "Application");
myClass1.ProcessServerLog("w2kserver", "directory
service");
myClass1.ProcessServerLog("w2kserver", "DNS
Server");
myClass1.ProcessServerLog("w2kserver", "file
replication service");
myClass1.ProcessServerLog
("w2kserver", "Security");
myClass1.ProcessServerLog
("w2kserver", "System");
Thread.Sleep(90000);
}
}
public void ProcessServerLog(string server, string log)
{
EventLog svrLog = new EventLog();
svrLog.MachineName = server;
svrLog.Log = log;
try
{
// Read entries from most-recent to oldest
for (int i = svrLog.Entries.Count - 1; i >= 0; i--)
{
Console.WriteLine("Reading: {0}/{1} - entry
number: {2}", server, log, i);
}
}
catch (System.InvalidOperationException e)
{
Console.WriteLine(">>>>ERROR processing event log
record: " + e.Message);
}
// Cleanup some objects
svrLog.Close();
svrLog = null;
}
}
}
Bryan Hunt - 21 Dec 2003 22:30 GMT
I should mention two additional things here:
First, although the code sample does not show it, I am
reading eventlog record fields (properties) in my program,
so instances are being created.
Second, I am using SQL connections in the program as
well. I just found out that there may be a bug in
the .Net SQL connections framework code that is indirectly
preventing my used eventlog objects from being garbage
collected.
I will update as I know more.
Bryan Hunt
>-----Original Message-----
>I hope that this the appropriate newsgroup for this
[quoted text clipped - 118 lines]
>
>.
Bryan Hunt - 25 Dec 2003 16:34 GMT
Problem solved!!
A big tip of the hat to Andreas Suurkuusk for figuring
this one out.
It turns out that, despite the fact that the memory that
wasn't being released was from the EventLogEntry
collection, the actual problem was a bug in the SQL
Connection framework code. Here is a bit from the message
that Andreas send to me:
================
One possibility is that this root is the f-reachable
queue. There exists an error with SqlConnections hanging
the f-reachable queue (if I remember it correctly it has
something to do with SqlConnections trying to marshal its
finalizer to the thread that created the connection).
Hanging the f-reachable queue will cause all finalizable
instances to become uncollectible. One way of solving
this problem is to apply a [MTAThread] attribute to your
Main method. This will work if your application does not
require the [STAThread] attribute (e.g. if it's not
a Windows Forms application).
================
Changing to MTAThread solved the problem for me. I would
have never figured that out by myself. BTW, Andreas'
company has a neat .Net memory profiling tool that helped
a lot in this debugging process. Here is a link to their
site:
http://www.scitech.se/memprofiler/Default.htm
Bryan Hunt
>-----Original Message-----
>I hope that this the appropriate newsgroup for this
[quoted text clipped - 118 lines]
>
>.