Click here to Skip to main content
15,891,937 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi guys,

I have a code something like this:
protected myclass[] _arr=new myclass[269999];
// some codes
while (LoopVar)
{
int Index=0;
lock (_arr.SyncRoot)
{
   myclass oM=_arr[Index];
}
lock (oM.SyncRoot)//SyncRoot is an object: public object SyncRoot=new object();
{
   //Some code
}
//Some code
Index++;
}

when I do this for a few times every things seems to be ok. but after a while when I repeat this for about 1000 times or more it seems that I have handles leak!! I have monitor this with DebugDiag and it says they are Event Handle and almost all of them are for
mscorwks!CLREvent::CreateMonitorEvent+30

Is this Normal?! and what is the life cycle of lock handles?
Is there any way to remove thease handles?
I have also tested GC.Collect(); GC.WaitForPendingFinalizers();
No change!

Note:
My array is alive during my Application.

Thanks,
Aidin
Posted
Updated 7-Dec-18 21:56pm

Locks and exceptions do not mix – Fabulous Adventures In Coding[^]

you may want to see how leaked locks are possible when using monitors. I think it's not the threads that saved your code but the fact that you had an if condition before the start of the thread (which atomically necessitates instructions before calling the thread) thereby causing the compiler to push some cpu instructions before the lock.

Leaking locks | C# Learners[^]
 
Share this answer
 
v2
Well, the lock statement is exactly the same as using

System.Threading.Monitor.Enter( object );
try
{
  //Do stuff
}
finally
{
  System.Threading.Monitor.Exit( object );
}

Which is likely where the CreateMonitorEvent thing is coming from. To be honest I wouldn't really worry about it. The only way I can think that you'd really be leaking handles is if you where acquiring locks but never releasing them, which seems unlikely.

Perhaps somebody with more knowledge of the inner workings can shed some more light, but like I said I wouldn't worry too much.
 
Share this answer
 
Comments
aidin Tajadod 5-Nov-10 0:46am    
Thanks SK Genius,
I am little worry about it, because it is a 24 7 windows service. and honesty I could not find any good article in the web that describe it a little more.
And about the Monitor, you are right.They are equal ( at least in theory, I have not looked at IL), But I change all my code to the lock to make sure Exit is called.
Now what about life cycle? Is it possible that OS or ... keeps the handle of a lock for performance reasons?
I mean when I call lock (object) {}, the object wont be destroyed during my App. so I am thinking maybe it is the reason for my handles leaking!!!!
Ok I think I have found the problem.
for those who want to know:

Try run a simple code below (C# windows App):

C#
public partial class Form1 : Form
{
    private const int ObjectCount = 1000;
    private const int ThreadCount = 50;
    System.Threading.Thread[] _Threads;
    Test[] _TestS=null;
    static bool bLoop = false;
    public Form1()
    {
        InitializeComponent();
    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        bLoop = true;
        _Threads = new System.Threading.Thread[ThreadCount];
        if (_TestS != null)
        {
            for (int i = 0; i < ObjectCount; i++)
            {
                _TestS[i].Dispose();
            }
            System.GC.Collect();
            System.GC.WaitForPendingFinalizers();
        }
        _TestS = new Test[ObjectCount];
        for (int i = 0; i < ObjectCount; i++)
        {
            _TestS[i] = new Test();
        }
        for (int i = 0; i < ThreadCount; i++)
        {
            _Threads[i] = new System.Threading.Thread(Do);
            _Threads[i].IsBackground = true;
        }
        for (int i = 0; i < ThreadCount; i++)
        {
            _Threads[i].Start();
        }
    }
    private void Do(object obj)
    {
        while (bLoop)
        for (int i = 0; i < ObjectCount; i++)
        {
            if (!bLoop) break;
            Test oTest;
            lock (_TestS.SyncRoot)
            {
                oTest = _TestS[i];
            }
            lock (oTest.SyncRoot)
            {
                oTest.DoSomething();
            }
        }
    }

    private void btnStop_Click(object sender, EventArgs e)
    {
        bLoop = false;
    }
}
public class Test:IDisposable
{
    public  object SyncRoot = new object();
    public void DoSomething()
    {
        System.Threading.Thread.Sleep(10);
    }
    public void Dispose()
    {
        SyncRoot = null;
    }
}

Handles count will increase about the value ObjectCount has!! (here is about 1000)
If I Stop it and agin start it, handles will increase again.
I tested System.GC.Collect(); System.GC.WaitForPendingFinalizers();
here and they seem that they work!! ( so handles are decreased and again increased.)
And I found one problem or maybe a bug in .net :
when I create a thread, OS or ... creates 4 handles for that. After the thread terminates, OS or ... will not realease those handles! So there are some Handles leak when we continuing create new threads. ( Thread pool is solved the problem)
And one thing else:
lock (object) {} will not increase the handles count if there are no other competitors! ( So I think in this situation, it does not call CLREvent::CreateMonitorEvent)
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900