【问题标题】:Why isn't my .NET garbage being collected?为什么我的 .NET 垃圾没有被收集?
【发布时间】:2015-03-06 11:59:23
【问题描述】:

我有一个数据密集型应用程序,用户可以在其中选择不同的帐户。一次只能选择一个帐户,这会强制从数据库加载数据。我可以在 Windows 任务管理器中看到,当我将帐户加载到大约半个演出时,分配给我的应用程序的内存正在增加。

我们还可以“卸载”一个帐户,从而删除内存中的所有对象(或者至少我们认为我们这样做了)。无论我让应用程序在我的 PC 上处于休眠状态多久,它似乎永远不会将分配的内存减少回预加载帐户状态,即使我使用 WeakReference 查看对象状态时说它不是 ALIVE。

如果我在卸载方法结束时显式调用GC.Collect(),那么我可以看到内存未分配或至少 Windows 任务管理器中的程序大小下降。这是我们真正希望在内存方面实现的目标,因为一些用户遇到了内存不足的异常。

我知道垃圾收集器正在做一些管理,因为如果我加载后续帐户,内存永远不会真正增加超过半个 gig,所以我认为 GC 已经收集了前一个帐户的数据,就像它在卸载帐户时应该做的那样。

我是否应该继续使用 GC.Collect 考虑到相对于从数据库加载帐户而言运行它的成本是最低的,即使明确调用它被认为是“不好的做法”?

【问题讨论】:

  • 在内存的情况下不要信任TaskManager。使用更可靠的东西作为性能监视器(在寡妇中键入 perfmon 来执行它),它显示工作集和私有字节。
  • 感谢您的评论 - 我将继续使用它

标签: c# .net memory-management memory-leaks


【解决方案1】:

根据您的描述,您似乎以某种方式保留了从数据库加载的项目的硬引用。如果您使用实体框架或 NHibernate,请检查您是否正在处理用于从数据库加载数据的上下文,因为它将保存您加载的所有内容的引用,以提供更改跟踪功能。一般来说,请确保您没有以某种方式保留参考,并注意有时这可能很棘手;棘手的硬引用的一个很好的例子是在使用方法范围变量的 lamda 方法中加载一些东西,由于在 lamda 方法内部被引用,该变量会自动提升为类变量。

【讨论】:

  • 您提到这一点很有趣,因为我们使用旧版 LinqToSQL ORM 进行数据访问。我们无法禁用 ORM 中的更改跟踪,因为我们的代码依赖于延迟加载模式,因为您不能启用延迟加载和禁用更改跟踪(我假设更改跟踪通知的事件注册可能会保留那些活着的物体)。我们最初抛出了内存异常,因为上下文没有被显式处理,在帐户更改期间处理它已经减少了这个问题。谢谢你的回答。
【解决方案2】:

GC回收只在certain events下触发(比如宿主进程分配的内存都用完了,需要分配更多,所以先看看能不能回收一些垃圾)。

OM 异常可能不是由此引起的,而是您在其他地方出现内存泄漏,或者某些用户试图加载多个帐户(甚至大于 0.5GB 的帐户)。考虑对您的应用程序进行一些内存分析。 (我为此使用了YourKit profiler,它非常易于使用)

认为如果您的进程是 x86,则它最多有 2GB 可用,因此使用如此大的数据并不少见,您会达到极限。

【讨论】:

  • 所以换句话说,我不应该质疑 .NET 运行时何时发生 GC 并避免使用 GC.Collect?如果我收到 Out-of-memory 异常,那么我应该专注于查找内存泄漏。
【解决方案3】:

我不知道您是否在代码中执行了此操作,但 using 语句将调用您正在使用的命令的 Dispose() 方法。它可能对您遇到问题的 GC 有所帮助。否则,您将让系统处理它。唯一的问题是您使用的类必须实现 IDisposable。

    using (SqlCommand cmd = conn.CreateCommand())
{
    conn.Open();
    cmd.CommandText = "sp_SaveSomething";
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new SqlParameter("@x", xxx));
    cmd.Parameters.Add(new SqlParameter("@ORG", ORG));        
    cmd.ExecuteNonQuery();
}

【讨论】:

    猜你喜欢
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 2014-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多