【问题标题】:C# Handles CountC# 句柄计数
【发布时间】:2015-03-10 10:21:50
【问题描述】:

我正在研究我的一个应用程序可能存在内存泄漏的可能性,因此开始使用一些非常基本的代码示例。我最终得到的一个,随着时间的推移,在句柄的数量(> 3000)方面开始大大增加。这是一个非常简单的控制台应用程序,代码如下:

public static void Main(string[] args)
{
    using (SqlConnection sqlConnection = new SqlConnection())
    {
    }

    Console.ReadLine();
}

取出 SqlConnection 调用会删除任何 Handle 增加,所以我假设它与连接池有关。但是由于它在基本上进入等待输入之前只运行一次,为什么 Handle 计数会不断增加?

谢谢。

【问题讨论】:

  • 如何检查句柄数?
  • 我使用任务管理器和进程资源管理器(sysinternals)。
  • a 内存泄漏是由于程序保留内存供自己使用并且在关闭时不释放,或者超过它自己的内存配额并写入被不同进程使用的块,操作系统应该阻止第二个,框架阻止第一个,所以除非你使用 Marshal 手动分配内存并且事后不清理内存泄漏不太可能是问题

标签: c#


【解决方案1】:

如果您在 .NET 4.0 上运行它,可能会出现这种情况

https://connect.microsoft.com/VisualStudio/feedback/details/691725/sqlconnection-handle-leak-net-4-0

【讨论】:

  • 谢谢蒂亚。这似乎是问题所在。我在项目中从 Framework 4.5.1 更改为 3.5,重新构建,现在 Handle 计数保持不变。因此,按照微软发布的上述内容,从线程池中收集的速度很慢,当应用程序中的足够活动导致 gc 启动时,句柄计数最终会下降。在.Net 4.0 中引入似乎仍然是一种奇怪的行为......也许与性能或其他东西有关......至少它清除了我所看到的。干杯。
【解决方案2】:

您会发现大部分对象缓存由框架对象组成,例如创建的对象,因此您可以访问配置文件和资源,而无需自己手动解析文件

IIRC 默认对象缓存约为 4000 个对象。

您必须记住,仅仅因为您只创建和处置单个对象并不意味着这就是框架所做的所有工作

【讨论】:

  • 感谢您的回复。我知道框架在后台做了很多事情。但是如果没有那个 SqlConnection 使用创建调用,应用程序句柄计数保持不变。因此,真正试图弄清一个调用启动或启动的确切内容,这会导致这种句柄计数行为。
  • 如果您查看 SQL 连接类,您会发现它包含其他类,例如 SqlConnection、DbProviderFactory、IContainer。 ISite、SecureString.、ConnectionState 等,因为您正确使用 using 命令在使用后处理连接对象,然后它将被 GC 的下一次运行拾取,因此应该没有泄漏。你 van 强制 GC 运行 GC.Collect()
  • 嗨 MikeT,再次感谢您的回复。由于指出 3.5 与 4.0 及更高版本的行为差异,我选择了 tia。但是,是的,可能强迫 GC 会降低它。虽然我知道这通常是不推荐的。可能会回落到 3.5。
  • 不推荐的原因是 GC 很昂贵并且会自动发生,自从我研究机制以来已经有一段时间了,但是有一个预定义的内存使用级别,当你的缓存超过这个大小时 GC 运行快速模式,然后有第二个级别,当您超过运行时,GC 是慢速模式,慢速模式比快速释放更多资源。因此,只要您不在系统上资源匮乏以至于预定义的使用级别非常危险,GC 就会在您遇到问题之前自动清理
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 1970-01-01
  • 1970-01-01
  • 2021-06-03
  • 2010-09-13
相关资源
最近更新 更多