Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.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
.net 超过垃圾收集器?_.net_Garbage Collection - Fatal编程技术网

.net 超过垃圾收集器?

.net 超过垃圾收集器?,.net,garbage-collection,.net,Garbage Collection,好的,这可能是一个noob问题,但现在开始 有可能“超过”垃圾收集器吗 我问这个问题的原因是因为我有一个递归方法,它在我的应用程序中的某个事件中运行了几次(我说的几次是指每秒大约60次,并且该事件会持续不确定的时间,甚至几分钟)。问题是,在递归方法的每个循环中,我都创建了一个相当复杂的对象(TreeViewItem,其中包含项目所需的一些mod,以及另一个作为TreeViewItem的DataContext的复杂对象),因此我关心的是,当递归方法运行时,这些TreeViewItem会留在堆中,因

好的,这可能是一个noob问题,但现在开始

有可能“超过”垃圾收集器吗

我问这个问题的原因是因为我有一个递归方法,它在我的应用程序中的某个事件中运行了几次(我说的几次是指每秒大约60次,并且该事件会持续不确定的时间,甚至几分钟)。问题是,在递归方法的每个循环中,我都创建了一个相当复杂的对象(TreeViewItem,其中包含项目所需的一些mod,以及另一个作为TreeViewItem的DataContext的复杂对象),因此我关心的是,当递归方法运行时,这些TreeViewItem会留在堆中,因此,当垃圾收集器启动时,它不会清理垃圾;很可能,下一次递归方法启动时,它会堆叠更多的TreeViewItem,垃圾收集器永远也追不上

问题是我们有内存泄漏,我们正在寻找罪魁祸首


任何真正需要的帮助

不,您不能“超越”垃圾收集器,它会在必要时中断您的代码。细节在一定程度上取决于您是否作为服务器运行

更大的问题是:为什么你认为你有内存泄漏?这就是你开始寻找原因的地方

请不要调用GC.Collect(),它弊大于利


增编1
内存管理可能出现的主要“问题”是将不再需要的引用保留在身边。通常,这对于流来说是很自然的,因为当方法返回时,局部变量被清除。但您应该查找对象之间设置的引用。一个值得注意的例子是EventHandler,如果您的对象订阅了一个事件,那么该订阅包含对订阅对象的引用。确保在不再需要时清除这些

垃圾收集器是否查看堆栈

我使用的那些线程只关心堆,如果ncessary可以停止所有线程,同时它们洗牌堆


你有什么证据可以证明你有漏洞,而不是一般来说有太多的东西?有时堆栈朝一个方向增长,堆在另一个方向——内存不足并不意味着“泄漏”。

我不相信这是真的;垃圾收集器通常隐式地绑定到内存分配中;因此,在分配内存时可以调用它;然而,我不是.Net框架如何进行垃圾收集的专家


内存泄漏(在托管代码中)最有可能的原因是您已完成的对象;但是仍然有对的引用。

GC只有在检测到需要运行时才会运行。换句话说,当它检测到有足够的内存压力需要一个收集周期时,通常(尽管这不是唯一的原因)是没有足够的堆空间来执行下一次分配


您需要寻找的一些东西是在循环中使用一次性对象,而不在之后处理它们(应该在使用块中完成),并在循环中执行大量字符串连接。


您需要确保正确地结束递归并备份调用堆栈。另外,是否需要为每个TreeViewItem设置DataContext?这是否可以在TreeView中设置一次,并让TreeView项遍历层次结构以找到适当的DataContext?

不,不能通过重载垃圾收集器使其泄漏

垃圾收集器的工作方式实际上使它能够很好地处理像您这样的情况

如果删除对大型复杂对象的引用,它将不会一次收集一个对象。它看到所有对象都不再有任何活动引用,它将立即收集所有对象

大多数对象的寿命都很短,因此构建垃圾收集器可以有效地处理这些对象。例如,如果您已经填充了第一代堆,并且要收集90%的对象,则垃圾收集器不会删除90%。相反,它会将10%移动到下一代,并简单地擦除第一代


如果垃圾收集器仍然发现自己有很多工作要做,它就会去做,而你将不得不等待它。它会在线程工作时冻结线程,在垃圾收集器完成之前它们不会运行。

如果这是您的问题:


每次运行此方法时 记忆一直在增长,记忆也在增长 发现它的程序员能够 之后到达OutOfMemoryException 高达1.5 GB(半小时内 小时)

然后,我建议将函数从循环中一次剥离一层(在有意义的层中),直到得到不会丢失内存的函数为止。然后将函数重新添加到微小的片段中,直到您确定导致泄漏的函数。

您无法“超越”垃圾收集器,但可能会对其造成严重压力。这通常表现为高CPU使用率,而不是GC没有清理需要清理的大块内存

如果您在半个小时内建立了OutOfMemoryException,那么肯定不是因为您使垃圾收集器过载。正如其他人所说,在应用程序运行时,对正在创建的新对象的引用更有可能保持活动状态。这并不意味着您应该将计时器循环设置为将所有内容都设置为空,您需要确定保留引用的原因,以及在您当前未完成的工作结束时,您应该采取什么措施来清理这些内容

这类工作的最佳工具是内存分析器。它们将分析活体对象以及应用程序中对它们的引用,并允许您找出您认为应该收集的哪些对象仍然活着,以及为什么。这就是你泄密的原因

总司令将确定
while true
   dim foo(4500000) as byte ' allocate 4.5 MB
   foo = nothing ' c# null - remove ref
end while