Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为我没有的对象释放内存';t设置为空_C#_.net_List_Memory_Console Application - Fatal编程技术网

C# 为我没有的对象释放内存';t设置为空

C# 为我没有的对象释放内存';t设置为空,c#,.net,list,memory,console-application,C#,.net,List,Memory,Console Application,编辑:问题与问题无关。我的代码确实出了问题,事实上,它太简单了,我不想把它放到网上。无论如何,谢谢你 我读取了大约550k条Active directory记录,并将它们存储在一个列表中,该类是广告用户的一个简单包装器。然后,我将记录列表分为四个列表,每个列表包含总数的四分之一。在我这样做之后,我从一个称为EDR记录的数据库中读入大约400k条记录到一个DataTable中。我获取列表中的四个四分之一并生成四个线程,每四个四分之一都通过。我现在必须使用电子邮件将广告记录与EDR记录进行匹配,但我

编辑:问题与问题无关。我的代码确实出了问题,事实上,它太简单了,我不想把它放到网上。无论如何,谢谢你

我读取了大约550k条Active directory记录,并将它们存储在一个列表中,该类是广告用户的一个简单包装器。然后,我将记录列表分为四个列表,每个列表包含总数的四分之一。在我这样做之后,我从一个称为EDR记录的数据库中读入大约400k条记录到一个DataTable中。我获取列表中的四个四分之一并生成四个线程,每四个四分之一都通过。我现在必须使用电子邮件将广告记录与EDR记录进行匹配,但我们计划稍后添加更多匹配的内容

我在AD记录列表上有一个foreach,在其中,我必须在EDR记录上运行for循环来检查每个记录,因为如果一个AD记录匹配多个EDR记录,那么这不是直接匹配,不应该被视为直接匹配

我的问题是,当我到达列表上的每一个foreach时,我的肾上腺记录列表中只有大约130条记录,但在我把它们全部拉进去之后,我就开始控制台。写入计数,它是544k

我开始认为,即使我没有将列表设置为空以便稍后收集,C#或Windows或其他东西实际上会将我的列表拿走,以便为EDR记录腾出空间,因为我已经有一段时间没有使用该列表了。我用来读取EDR记录的数据库是一个链接服务器,所以读取所有记录大约需要10分钟,所以我的列表实际上空闲了10分钟,但它从未设置为null

有什么想法吗

//splitting list and passing in values to threads.
List<ADRecord> adRecords = GetAllADRecords();
        for (int i = 0; i < adRecords.Count/4; i++)
        {
            firstQuarter.Add(adRecords[i]);
        }
        for (int i = adRecords.Count/4; i < adRecords.Count/2; i++)
        {
            secondQuarter.Add(adRecords[i]);
        }
        for (int i = adRecords.Count/2; i < (adRecords.Count/4)*3; i++)
        {
            thirdQuarter.Add(adRecords[i]);
        }
        for (int i = (adRecords.Count/4)*3; i < adRecords.Count; i++)
        {
            fourthQuarter.Add(adRecords[i]);
        }
        DataTable edrRecordsTable = GetAllEDRRecords();

        DataRow[] edrRecords = edrRecordsTable.Select("Email_Address is not null and Email_Address <> ''", "Email_Address");
        Dictionary<string, int> letterPlaces = FindLetterPlaces(edrRecords);
        Thread one = new Thread(delegate() { ProcessMatches(firstQuarter, edrRecords, letterPlaces); });
        Thread two = new Thread(delegate() { ProcessMatches(secondQuarter, edrRecords,  letterPlaces); });
        Thread three = new Thread(delegate() { ProcessMatches(thirdQuarter, edrRecords,  letterPlaces); });
        Thread four = new Thread(delegate() { ProcessMatches(fourthQuarter, edrRecords, letterPlaces); });
        one.Start();
        two.Start();
        three.Start();
        four.Start();
//拆分列表并将值传递给线程。
List adRecords=GetAllADRecords();
对于(int i=0;i

在ProcessMatches中,传入的肾上腺记录列表中有一个foreach。foreach中的第一行是AdRecordsProcessed++;这是一个全局静态int,程序以130结束,而不是544k。

该变量从未设置为null,并且仍在范围内?如果是这样,它就不应该被收集,空闲时间也不是你的问题

我看到的第一个问题是:

AdRecordsProcessed++; 
在更新全局变量之前是否锁定了它?如果不是,并且取决于处理记录的速度,它将比您预期的低


尝试从单个线程运行它(即传入adRecords而不是第一个季度,并且不要启动其他线程)。它在1个线程中是否按预期工作?

首先,不要将列表设置为null。您可能要做的是将对列表的每个引用设置为null(或另一个列表),否则所有此类引用都可能超出范围。这似乎是一个吹毛求疵的地方,但如果你不得不检查你的数据发生了什么,那么是时候对这些事情吹毛求疵了

其次,让GC取消分配具有活动引用的内容是相当困难的。你可以用一个WeakReference来伪装它,或者当你在最终用户中遇到一个bug时认为你已经找到了它(因为该引用实际上不是活动的,即使这样,最终用户也会试图处理一个最终用户而不是被解除分配的对象)。bug可能到处都会发生,但是您已经找到了一种方法使GC取消分配一些活动的东西,这是非常不可能的

GC可能会对您的列表做两件事:

  • 它很可能会压缩所使用的内存,从而移动其组件项
  • 很有可能把它推广到更高一代
  • 除非您实际查找它们,否则这两个函数都不会有任何变化(显然,如果您一直调用GetGeneration(),您会注意到生成中的变化,但除此之外,您实际上不会这样做)

    使用的内存也可以被调出,但当您使用对象时,它将被调回。同样,您不会注意到任何影响

    最后,如果GC确实解除分配了某些对象,那么项目的数量就不会减少,就会发生崩溃,因为如果对象刚刚被解除分配,系统仍然会尝试使用假定的活动引用

    因此,尽管GC或OS可能会为您的其他对象腾出空间,但它在代码中是不可见的,并且它不会阻止对象可用并处于相同的编程状态


    问题出在其他方面。

    是否有理由一次获取所有数据?如果您将数据分成块,它应该更易于管理。我所知道的是进入GC的东西有点臭。最好看看重构代码。

    垃圾收集器将收集:<