c#lock处理泄漏 [英] c# lock handles leak

查看:78
本文介绍了c#lock处理泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,



我的代码如下:

 protected myclass [] _arr = new myclass [269999]; 
//一些代码
而(LoopVar)
{
int Index = 0;
lock(_arr.SyncRoot)
{
myclass oM = _arr [Index];
}
lock(oM.SyncRoot)// SyncRoot是一个对象:公共对象SyncRoot = new object();
{
//一些代码
}
//一些代码
Index ++;
}



当我这样做几次时,每件事似乎都没问题。但过了一段时间,当我重复这个约1000次或更多时,似乎我有处理泄漏!我用DebugDiag监视它,它说它们是事件句柄,几乎所有它们都用于

mscorwks!CLREvent :: CreateMonitorEvent + 30


$ b这是正常的吗?!锁把手的生命周期是什么?

有没有办法删除这些句柄?

我也测试了GC.Collect(); GC.WaitForPendingFinalizers();

无变化!



注意:

我的应用程序期间我的数组处于活动状态。



谢谢,

Aidin

解决方案

锁和异常不混合 - 编码中的神话般的冒险 [ ^ ]



你可能想看看使用显示器时泄漏锁是如何实现的。我认为这不是保存代码的线程,而是在线程开始之前你有一个if条件的事实(在调用线程之前原子地需要指令)从而导致编译器在锁之前推送一些cpu指令。 />


泄漏锁| C#学员 [ ^ ]

好吧,锁定语句与使用完全相同



 System.Threading.Monitor.Enter(object ); 
try
{
//做东西
}
最后
{
System.Threading.Monitor.Exit(object);
}



这可能是CreateMonitorEvent的来源。说实话,我真的不担心。我认为你真正泄漏手柄的唯一方法就是如果你在哪里获得锁定而从不释放它们,这似乎不太可能。



也许有更多知识的人内部工作可以带来更多的亮点,但就像我说我不会太担心。


好的我想我找到了问题。

对于那些想知道的人:



尝试在下面运行一个简单的代码(C#windows App):



  public   partial   class  Form1:表格
{
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] = System.Threading.Thread(Do);
_Threads [i] .IsBackground = true ;
}
for int i = 0 ; i < ThreadCount; i ++)
{
_Threads [i] .Start();
}
}
私有 void Do( object obj)
{
while (bLoop)
for int i = 0 ; i < ObjectCount; i ++)
{
if (!bLoop);
测试oTest;
lock (_ TestS.SyncRoot)
{
oTest = _TestS [i];
}
lock (oTest.SyncRoot)
{
oTest.DoSomething();
}
}
}

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



句柄数量会增加大约ObjectCount的值!! (这里大概是1000)

如果我停止它并且agin启动它,句柄将再​​次增加。

我测试了System.GC.Collect(); System.GC.WaitForPendingFinalizers();

在这里,他们似乎工作了! (因此句柄减少并再次增加。)

我在.net中发现了一个问题或者可能是一个错误:

当我创建一个线程,操作系统或...为此创建4个句柄。线程终止后,OS或...将不会释放这些句柄!因此,当我们继续创建新线程时,会有一些Handles泄漏。 (线程池解决了问题)

还有一件事:

lock(object){}如果没有其他竞争对手,将不会增加句柄数! (所以我认为在这种情况下,它不会调用CLREvent :: CreateMonitorEvent)


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

解决方案

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[^]


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.


Ok I think I have found the problem.
for those who want to know:

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

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)


这篇关于c#lock处理泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆