Leakage leak in .Net streams

It actually bit me a couple of times. If you are doing simple code as follows:

private void button1_Click(object sender, EventArgs e) { for (int i = 0; i < 1000000; i++) { Thread CE = new Thread(SendCEcho); CE.Priority = ThreadPriority.Normal; CE.IsBackground = true; CE.Start(); Thread.Sleep(500); GC.Collect(); } } private void SendCEcho() { int Counter = 0; for (int i = 0; i < 5; i++) { Counter++; Thread.Sleep(25); } } 

Run this code and see how the pens fly! Thread.Sleep is that you can close it and not take over the computer. This should ensure that the thread starts before the start of the next thread. Call GC.Collect (); doing nothing. From my observation, this code loses 10 descriptors of each update in the task manager during a normal update.

It doesn't matter what is in the void SendCEcho () function, if you want, count to five. When the thread dies, there is one handle that does not peel.

In most programs, this does not matter much because they do not work for long periods of time. In some programs that I created, they should run within a few months and months.

If you use this code again and again, you can eventually test the descriptors until the time that Windows becomes unstable and will not work. Reboot required.

I solved the problem using a thread pool and code like this:

 ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadJobMoveStudy)); 

My question, however, is why there is such a leak in .Net and why does it exist for so long? So how is 1.0? I could not find the answer here.

+5
source share
3 answers

Try adding GC.WaitForPendingFinalizers(); after calling GC.Collect (); I think you will get what you need. Full source code below:

EDIT

Also take a look at this from 2005: https://bytes.com/topic/net/answers/106014-net-1-1-possibly-1-0-also-threads-leaking-event-handles-bug . Almost the same code as yours.

 using System; using System.Threading; class Program { static void Main(string[] args) { for (int i = 0; i < 1000000; i++) { Thread CE = new Thread(SendCEcho); CE.Priority = ThreadPriority.Normal; CE.IsBackground = true; CE.Start(); Thread.Sleep(500); CE = null; GC.Collect(); GC.WaitForPendingFinalizers(); } } public static void SendCEcho() { int Counter = 0; for (int i = 0; i < 5; i++ ) { Counter++; Thread.Sleep(25); } } } 
+3
source

You create threads that never end. SendCEcho for SendCEcho never ends, so threads never end, and therefore cannot be restored. If I fix your loop code, the threads will end and be fixed as expected. I can not reproduce the problem with the code below.

 static void SendCEcho() { int Counter = 0; for (int i = 0; i < 5; i++) { Counter++; Thread.Sleep(25); } } 
+5
source
  for (int i = 0; i < 5 + i++; ) 

Pretty weird typo, you haven't created your real problem yet. There is one thing: the Thread object consumes 5 operating system descriptors, its internal finalizer releases them. The .NET class usually has a Dispose () method to ensure that such descriptors can be released earlier, but Thread does not. It was a bold design, such a Dispose () method would be very difficult to call.

Therefore, the need to rely on the finalizer is a strict requirement. In a program that has the SendEcho method and does nothing, you risk that the garbage collector never starts. Therefore, the finalizer cannot do its job. Then you need to call GC.Collect () yourself. You would think about this, say, the 1000 threads that you start. Or use ThreadPool.QueueUserWorkItem () or Task.Run () to get you to process threads, a logical approach.

Use Perfmon.exe to verify that the GC does not really start. Add a collection counter to the .NET CLR Memory> # Gen 0 console.

+5
source

Source: https://habr.com/ru/post/1236654/


All Articles