gpt4 book ai didi

C#:释放内存使用

转载 作者:行者123 更新时间:2023-11-30 15:13:25 24 4
gpt4 key购买 nike

我需要为开箱即用的问题执行一个漫长而繁重的过程。所以我把流程分成了多个子流程。现在的问题是如何在每个窗口执行之前释放内存。

举个例子更容易解释。让我们看一下这个伪代码。

1. Some earlier code to do other things
2. Do
3. Raise a Task
4. If raised-task > 1000
5. Wait all raised task to finish
6. Release Memory
7. End If
8. Wile Something not relevant

有了这个想法,我开发了下一个方法,每次达到线程限制时都会执行该方法:

List<Task> LTask();
//It's not relevant, but this list is populate like
//var task = Task.Run(() => something());
//LTask.Add(task);

private void waitForAll()
{
//Break point 1
Task.WhenAll(LTasks).Wait();

LTasks.Clear();
LTasks = null;
GC.Collect();
GC.WaitForPendingFinalizers();

//Break point 2
LTasks = new List<Task>();
}

我预计内存会围绕某些值保持不变(略有变化)。我的意思是:

  1. 达到线程限制
  2. BreakPoint 1 中使用 visual studio 诊断工具的内存使用快照 --> 100MB
  3. BreakPont 2 中使用 visual studio 诊断工具的内存使用快照 --> 100 MB。 第一个问题,为什么这个没有减少?所有的线程都结束了,我强制垃圾收集器执行。

下次达到限制并执行此代码时,如果我再次拍摄快照,内存将继续增加:200、300、...

这是一个捕获诊断工具。每次到达断点 1 时拍摄奇数快照,在断点 2 时拍摄偶数快照。

enter image description here

第二个问题,在抛出Out of memory Exception之前,它会继续无限增加吗?

最后一个问题,有什么替代方案可以解决问题并释放内存吗?

更新 1:经过一些测试,并感谢评论,我开发了一个测试代码,以深入研究它。必须涉及其他事情。请看下一段代码。内存继续增加,没有限制。

private List<Task> LTasks = new List<Task>();
private void manageThreadholdLimit()
{
waitForAll();
realeaseMemory();
}

private void waitForAll()
{
Task.WhenAll(LTasks).Wait();
LTasks.Clear();
LTasks = null;
}
private void realeaseMemory()
{
GC.Collect();
GC.WaitForPendingFinalizers();

LTasks = new List<Task>();
}
public void Main(){
int i = 0;

while (true)
{
i++;

var task = Task.Run(() => Thread.Sleep(100));
LTasks.Add(task);

//Si hemos alcanzado el máximo de paralelismo, esperamos la conclusión
if (i % 1000 == 0) manageThreadholdLimit();

}
}

最佳答案

不保证 GarbageCollector 在您取消引用对象后立即运行。事实上,它可能不会。即使您想使用 GC.Collect() 手动调用它进行测试,您也无法真正保证它会立即运行。此外,经常调用 GC 也是有代价的。可以使用 RAM(至少在具有大量 RAM 的较新机器中是这样……)。如果你的内存力上升,并在较长时间后保持不变,那你就有问题了。这通常表示您有其他一些内存问题。也许你漏气了?

如果我们谈论的是免费解决方案,您可以使用 ProcessExplorerCLR Profiler寻找潜在的内存问题。 Here是一篇关于如何做到这一点的文章。

注意事项:

  1. 尽快将对对象的引用设置为null。你完成了列表?将其值设置为 null
  2. 将处理大量数据的方法拆分为更小的方法 - 即使您将某些内容设置为 null,GC 也不会运行,直到方法退出。
  3. 检查您是否在需要的地方正确实现了终结器。
  4. 确保没有泄漏:检查您正在使用的对象是否未从工作方法外部引用。要特别注意事件处理程序和数据绑定(bind)。

此外,Task.WhenAll() 显然保留了对其所有“子”任务的引用。如果您在同一方法之后立即手动调用 GC,我认为它有可能无法触及该内存,因为该方法本身仍在“引用”它。

Here是一篇关于垃圾回收的 MSDN 文章。

关于C#:释放内存使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58935327/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com