Hi,
Threads in the .NET Framework 1.1 (and possibly in 1.0 also) leak "Event"
handles, by Event handles I mean Win32 Event handles which can be monitored
using the ProcessExplorer from www.sysinternals.com, or even simply look at
the Handle count in the good old windows TaskManager.
To demonstrate the problem, all I did was created a basic Win Forms
application and with Main implemented as:
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
and Form's constructor as
public Form1()
{
while(true)
{
Thread thread = new Thread( new ThreadStart( ThreadProc) );
thread.Start();
Thread.Sleep(1000);
GC.Collect();
}
}
and the ThreadProc is implemented simply as
protected void ThreadProc()
{
Thread.Sleep(100);
return;
}
Now you let it run for a while and monitor the handle count using the
ProcessExplorer or TaskManager to can see that the thread count becomes more
or less constant after a bit (which means that an equilibrium is reached in
which the threads being created and thread which die is same), you will note
that the Handle count keeps on increasing. I have monitored upto 10000
handles after which I killed the application.
Now, this seems like a bug. Has someone got any explaination for this and
possibly a workaround. BTW, I also tried changing the attribute on Main from
STAThread to MTAThread with no change in behavior.
Any help/suggestions would be appreciated.
thanks,
Rohit 11 3608
Please, try this from a console type application, and you will see that
there are no 'event' handle leaks related to the Thread start delegate.
If there's a leak is somewhere else in your code, could you post a complete
repro sample.
Willy.
"Rohit" <no****@nospam.org> wrote in message
news:uM**************@TK2MSFTNGP11.phx.gbl... Hi,
Threads in the .NET Framework 1.1 (and possibly in 1.0 also) leak "Event" handles, by Event handles I mean Win32 Event handles which can be
monitored using the ProcessExplorer from www.sysinternals.com, or even simply look
at the Handle count in the good old windows TaskManager. To demonstrate the problem, all I did was created a basic Win Forms application and with Main implemented as:
[STAThread] static void Main() { Application.Run(new Form1()); }
and Form's constructor as public Form1() { while(true) { Thread thread = new Thread( new ThreadStart( ThreadProc) ); thread.Start(); Thread.Sleep(1000); GC.Collect(); } } and the ThreadProc is implemented simply as protected void ThreadProc() { Thread.Sleep(100); return; }
Now you let it run for a while and monitor the handle count using the ProcessExplorer or TaskManager to can see that the thread count becomes
more or less constant after a bit (which means that an equilibrium is reached
in which the threads being created and thread which die is same), you will
note that the Handle count keeps on increasing. I have monitored upto 10000 handles after which I killed the application. Now, this seems like a bug. Has someone got any explaination for this and possibly a workaround. BTW, I also tried changing the attribute on Main
from STAThread to MTAThread with no change in behavior. Any help/suggestions would be appreciated.
thanks, Rohit
Rohit wrote: Hi,
Threads in the .NET Framework 1.1 (and possibly in 1.0 also) leak "Event" handles, by Event handles I mean Win32 Event handles which can be monitored using the ProcessExplorer from www.sysinternals.com, or even simply look at the Handle count in the good old windows TaskManager. To demonstrate the problem, all I did was created a basic Win Forms application and with Main implemented as:
[STAThread] static void Main() { Application.Run(new Form1()); }
and Form's constructor as public Form1() { while(true) { Thread thread = new Thread( new ThreadStart( ThreadProc) ); thread.Start(); Thread.Sleep(1000); GC.Collect();
I cannot see a _real_ problem with any of your sample code when you add
explict calls to GC.Collect /and/ GC.WaitForPendingFinalizers. Thread has a
Protected Finalize and does not implement the IDisposable interface, so its
unmanaged handles (which seem to correspond to a Win32 Thread handle and a
handful of Event handles) don't get cleaned up until the GC get around to it.
And with an infinite loop creating threads, your test isn't going to do GC
until it determines there's a pressing need to do so.
So it's not really a bug, just an 'interesting' design decision to not provide
IDisposable for Thread.
BTW Anyone got a good way of forcing a running .NET process' GC to do a
collection?
--
Regards,
Mark Hurd, B.Sc.(Ma.) (Hons.)
> BTW Anyone got a good way of forcing a running .NET process' GC to do a collection?
GC.Collect() and GC.WaitForPendingFinalizers() will do it, but if you want
to reduce the working set you have to act on the Process class. Here's my
sample: http://blogs.geekdojo.net/richard/posts/338.aspx
Richard
--
C#, .NET and Complex Adaptive Systems: http://blogs.geekdojo.net/Richard
"Mark Hurd" <ma******@ozemail.com.au> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl... Rohit wrote: Hi,
Threads in the .NET Framework 1.1 (and possibly in 1.0 also) leak "Event" handles, by Event handles I mean Win32 Event handles which can be monitored using the ProcessExplorer from www.sysinternals.com, or even simply look at the Handle count in the good old windows TaskManager. To demonstrate the problem, all I did was created a basic Win Forms application and with Main implemented as:
[STAThread] static void Main() { Application.Run(new Form1()); }
and Form's constructor as public Form1() { while(true) { Thread thread = new Thread( new ThreadStart( ThreadProc) ); thread.Start(); Thread.Sleep(1000); GC.Collect(); I cannot see a _real_ problem with any of your sample code when you add explict calls to GC.Collect /and/ GC.WaitForPendingFinalizers. Thread has
a Protected Finalize and does not implement the IDisposable interface, so
its unmanaged handles (which seem to correspond to a Win32 Thread handle and a handful of Event handles) don't get cleaned up until the GC get around to
it. And with an infinite loop creating threads, your test isn't going to do GC until it determines there's a pressing need to do so.
So it's not really a bug, just an 'interesting' design decision to not
provide IDisposable for Thread.
BTW Anyone got a good way of forcing a running .NET process' GC to do a collection? -- Regards, Mark Hurd, B.Sc.(Ma.) (Hons.)
Richard A. Lowe wrote: BTW Anyone got a good way of forcing a running .NET process' GC to do a collection?
GC.Collect() and GC.WaitForPendingFinalizers() will do it, but if you want to reduce the working set you have to act on the Process class. Here's my sample: http://blogs.geekdojo.net/richard/posts/338.aspx
Good stuff, but I'm refering to a running .NET sample like the one in this
thread. Is there a good way to get the GC to decide it should run even though
the process is busy.
I'm running the OP's sample code and it's got to over 21000 handles and I know
they're all ready for garbage collection. I assume I need to temporarily max
out one of the resources the GC monitors to determine when it should run
immediately, but I couldn't find a way that doesn't just cause random programs
to fail with out of memory errors...
--
Regards,
Mark Hurd, B.Sc.(Ma.) (Hons.)
"Rohit" <no****@nospam.org> wrote in message
news:OH**************@TK2MSFTNGP10.phx.gbl... Hi Willy, Thanks for your reply, I will try in a console application, however in the meanwhile here is a small test app (basically its a win forms application
in C#) that will demonstrate the problem. I have attached a zip file
containing the whole project. One quick note, this is a small app so I'm creating threads from inside
the Form's constructor so you will not see the window come up (since the initialization of the main form never completes). However this has no
effect on the handle leak even if I were to start thread creation from outside. thanks again, Rohit
Ok I see, you do not call GC.Collect.
But what you observe is not a leak, in this small sample, the only objects
that get allocated on the GC heap are the Thread objects (~60 bytes/object),
Thread objects have an associated OS handle and a synchronization event
handle, so before the GC kicks in (for the second time) you will have
allocated thousands of them.
Now, in a real world application the GC will run more often and what you
observe now will not show up.
Willy.
Hi,
Thanks all for your input.
I had (before posting this question on this messageboard) played with
calling GC.Collect() and also GC.WaitForPendingFinalizers() explicitly, and
yes I do agree that in this small application the handles do get cleaned
out.
However, what actually prompted all this exercise is that in the product
that I'm working on we are seeing a similar handle leak. Now, thats a
remoting based application with a service running on the server side to
which client (one or more) connect and then do the stuff and then
disconnect. Now, in this application we are seeing a handle leak when we do
a regression testing. So, I started eliminating code to see what I find. So,
the smallest bit of code that still leaks handle goes like this:
A Singleton object is exposed remotly.
from another application, I make remoting calls, get this remote object, and
then call a method in this object. This method starts a thread, where in
ThreadProc is implemented like below and then returns.
protected void ThreadProc()
{
Thread.Sleep(1000);
GC.Collect();
return;
}
Even this code, despite my calling GC.Collect() is showing an increase in
handle count. And if I moniter using the new ProcessExplorer from
SysInternals.Com, which shows the number of GC calls (for Gen 0, 1 and 2),
or if I use PerfMon which also shows the GC calls, I see that the GC is
being called, but even then the handle count of thread and event objects is
growing.
Now, is it possible, that GC is ignoring (or in other words "incorrectly
handling") thread and event handles (i.e. objects of class Thread) and not
proper garbage collecting them, in a remoting scenario or in a scenario
where there are other objects to be collected it leaves behind the Thread
objects.
Any help in this regard would be greatly appreciated,
thanks,
Rohit
"Willy Denoyette [MVP]" <wi*************@pandora.be> wrote in message
news:ux**************@TK2MSFTNGP09.phx.gbl... "Rohit" <no****@nospam.org> wrote in message news:OH**************@TK2MSFTNGP10.phx.gbl... Hi Willy, Thanks for your reply, I will try in a console application, however in
the meanwhile here is a small test app (basically its a win forms
application in C#) that will demonstrate the problem. I have attached a zip file containing the whole project. One quick note, this is a small app so I'm creating threads from inside the Form's constructor so you will not see the window come up (since the initialization of the main form never completes). However this has no effect on the handle leak even if I were to start thread creation from outside. thanks again, Rohit
Ok I see, you do not call GC.Collect. But what you observe is not a leak, in this small sample, the only
objects that get allocated on the GC heap are the Thread objects (~60
bytes/object), Thread objects have an associated OS handle and a synchronization event handle, so before the GC kicks in (for the second time) you will have allocated thousands of them. Now, in a real world application the GC will run more often and what you observe now will not show up.
Willy.
Mark,
If you run OP's console sample (including GC.Collect(), you will see that
the GC run's every second.
Willy.
"Mark Hurd" <ma******@ozemail.com.au> wrote in message
news:OV**************@TK2MSFTNGP12.phx.gbl... Richard A. Lowe wrote: BTW Anyone got a good way of forcing a running .NET process' GC to do a collection? GC.Collect() and GC.WaitForPendingFinalizers() will do it, but if you want to reduce the working set you have to act on the Process class. Here's my sample: http://blogs.geekdojo.net/richard/posts/338.aspx
Good stuff, but I'm refering to a running .NET sample like the one in this thread. Is there a good way to get the GC to decide it should run even
though the process is busy.
I'm running the OP's sample code and it's got to over 21000 handles and I
know they're all ready for garbage collection. I assume I need to temporarily
max out one of the resources the GC monitors to determine when it should run immediately, but I couldn't find a way that doesn't just cause random
programs to fail with out of memory errors... -- Regards, Mark Hurd, B.Sc.(Ma.) (Hons.)
"Rohit" <no****@nospam.org> wrote in news:#5vZu52vDHA.2520
@TK2MSFTNGP10.phx.gbl:
Here's what I ran:
using System;
using System.Threading;
class Class1
{
static void Main(string[] args)
{
while(true)
{
Thread thread = new Thread(new ThreadStart(ThreadProc));
thread.Start();
Thread.Sleep(1000);
GC.Collect();
}
}
static void ThreadProc()
{
Thread.Sleep(1500);
return;
}
}
No handle leak here.
Mark
Hi,
Thanks all for your input.
I had (before posting this question on this messageboard) played with
calling GC.Collect() and also GC.WaitForPendingFinalizers() explicitly, and
yes I do agree that in this small application the handles do get cleaned
out.
However, what actually prompted all this exercise is that in the product
that I'm working on we are seeing a similar handle leak. Now, thats a
remoting based application with a service running on the server side to
which client (one or more) connect and then do the stuff and then
disconnect. Now, in this application we are seeing a handle leak when we do
a regression testing. So, I started eliminating code to see what I find. So,
the smallest bit of code that still leaks handle goes like this:
A Singleton object is exposed remotly.
from another application, I make remoting calls, get this remote object, and
then call a method in this object. This method starts a thread, where in
ThreadProc is implemented like below and then returns.
protected void ThreadProc()
{
Thread.Sleep(1000);
GC.Collect();
return;
}
Even this code, despite my calling GC.Collect() is showing an increase in
handle count. And if I moniter using the new ProcessExplorer from
SysInternals.Com, which shows the number of GC calls (for Gen 0, 1 and 2),
or if I use PerfMon which also shows the GC calls, I see that the GC is
being called, but even then the handle count of thread and event objects is
growing.
Now, is it possible, that GC is ignoring (or in other words "incorrectly
handling") thread and event handles (i.e. objects of class Thread) and not
proper garbage collecting them, in a remoting scenario or in a scenario
where there are other objects to be collected it leaves behind the Thread
objects.
Any help in this regard would be greatly appreciated,
thanks,
Rohit
"Mark" <mark@--somewhere--.com> wrote in message
news:Xn******************************@207.46.248.1 6... "Rohit" <no****@nospam.org> wrote in news:#5vZu52vDHA.2520 @TK2MSFTNGP10.phx.gbl:
Here's what I ran:
using System; using System.Threading;
class Class1 { static void Main(string[] args) { while(true) { Thread thread = new Thread(new ThreadStart(ThreadProc)); thread.Start(); Thread.Sleep(1000); GC.Collect(); } }
static void ThreadProc() { Thread.Sleep(1500); return; } } No handle leak here.
Mark
> "Mark Hurd" <ma******@ozemail.com.au> wrote in message news:OV**************@TK2MSFTNGP12.phx.gbl... Richard A. Lowe wrote: > BTW Anyone got a good way of forcing a running .NET process' GC > to do a collection?
Willy Denoyette [MVP] wrote: Mark,
If you run OP's console sample (including GC.Collect(), you will see that the GC run's every second.
Yes. However, in the general case, say a test program or a threaded Mandelbrot
set generator, etc, can a system admin (not the programmer redesigning the
source) kick the GC into action externally?
In posing this question I was assuming the GC automatically checked other
Windows resources than memory (quite implicitly). Once I realised this is
probably not what an "Automatic memory management system" does, and I've
confirmed it:
Other than managed memory allocations, implementations of the
garbage collector do not maintain information about resources
held by an object, such as file handles or database connections.
(from About GC Class in the 1.1.1 docs.)
And yes, this is obvious in hindsight. I was just in a Windows frame of mind
when thinking about this.
So, I suppose it comes down to, "Is there an external API, or other 'hook',
(perhaps normally for debugging) that can initiate a GC?"
--
Regards,
Mark Hurd, B.Sc.(Ma.) (Hons.)
Mark Hurd wrote: Rohit wrote: Hi,
Threads in the .NET Framework 1.1 (and possibly in 1.0 also) leak "Event" handles, by Event handles I mean Win32 Event handles which can be monitored using the ProcessExplorer from www.sysinternals.com, or even simply look at the Handle count in the good old windows TaskManager. To demonstrate the problem, all I did was created a basic Win Forms application and with Main implemented as:
[STAThread] static void Main() { Application.Run(new Form1()); }
and Form's constructor as public Form1() { while(true) { Thread thread = new Thread( new ThreadStart( ThreadProc) ); thread.Start(); Thread.Sleep(1000); GC.Collect();
I cannot see a _real_ problem with any of your sample code when you add explict calls to GC.Collect /and/ GC.WaitForPendingFinalizers. Thread has a Protected Finalize and does not implement the IDisposable interface, so its unmanaged handles (which seem to correspond to a Win32 Thread handle and a handful of Event handles) don't get cleaned up until the GC get around to it. And with an infinite loop creating threads, your test isn't going to do GC until it determines there's a pressing need to do so.
So it's not really a bug, just an 'interesting' design decision to not provide IDisposable for Thread.
I think Eric G has described the issue well here: http://blogs.gotdotnet.com/EricGu/pe...2-6b1e3830988d
The difference being, the GDI wrappers can be Disposed, but Thread cannot.
--
Regards,
Mark Hurd, B.Sc.(Ma.) (Hons.) This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Andy Read |
last post by:
Hello all,
I have the requirement to produce source code that produces an object
hierarchy.
Example:
Root
|
Folder 1
|
by: Eddy Bee |
last post by:
Hi there,
I'm encountering an inexplicable problem with page formatting in
reports. Here's the easiest way to explain it:
The Detail section of my report contains two elements:
And let's...
|
by: lovecreatesbeauty |
last post by:
Hello,
I want to know whether programming languages such as C or C++ provide
something like "event".
In function "f1", a handler/function "h2" is triggered. But f1 won't be
blocked by h2,...
|
by: Billy |
last post by:
Anyone know if this a bug in VB.NET 2002 and how to overcame that
situation?
I have a MDI form from where I call MDI child form like that:
Dim frm As New frmChild()
frm.MdiParent = Me...
|
by: Rohit |
last post by:
Hi,
Threads in the .NET Framework 1.1 (and possibly in 1.0 also) leak "Event"
handles, by Event handles I mean Win32 Event handles which can be monitored
using the ProcessExplorer from...
| |
by: Jason |
last post by:
Hello,
I am trying to dynamically create a table, then set its <td>'s onclick:
var table = document.createElement("table");
var row = table.insertRow(-1);
var td = row.insertCell(-1);...
|
by: diff |
last post by:
I am having trouble preventing a bound source from updating using event-driven validation.
There is a very nice article on MSDN explaining this;...
|
by: Gregor Kofler |
last post by:
I'm trying to "detect" a keydown event in a DIV.
The idea have a keydown listener attached to document and forward the
event to the div. (I've searched the web, but it was impossible to
handle...
|
by: Fresno Bob |
last post by:
I have a script manager in my Master Page. I want use the Ajax history
functionality. This means code in my content page needs to be called when
the navigate event fires in the master. How can I...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
| |
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |