IDisposable:内存泄漏

时间:2011-11-07 16:29:55

标签: c# memory-leaks idisposable

我目前正在审核一个C#应用程序,其中我看到了:

public static bool ServiceExists(string servicename)
{
    ServiceController[] services = ServiceController.GetServices();
    foreach (ServiceController s in services)
    {
        if (s.ServiceName == servicename)
        {
            return true;
        }
    }
    return false;
}

在这个answer中,Henk说不使用Dispose()(或using)不会产生内存泄漏,无论是真还是假?

我可以保留以前的代码吗或者我应该写一些像:

public static bool ServiceExists(string servicename)
{
    ServiceController[] services = ServiceController.GetServices();
    bool exists = false;

    foreach (ServiceController s in services)
    {
        using(s)
        {
            if (s.ServiceName == servicename)
            {
                exists = true;
            }
        }
    }

    return exists;
}

在这种情况下,不使用Dispose()(或using)会有什么风险?

2 个答案:

答案 0 :(得分:6)

如果未调用Dispose方法,则正确编写的对象不应导致内存泄漏。目前,控制非托管资源的.Net对象应该通过SafeHandle实例来实现。这些将确保即使未调用Dispose也释放本机内存。

但是,如果未调用Dispose,则未正确写入的对象很可能会产生内存泄漏。我见过很多这样的对象的例子。

一般情况下,如果您使用的是您拥有的IDisposable个实例,则应始终致电Dispose。即使对象写得正确,也可以提前清理非托管资源,而不是以后清理。

修改

正如James在评论中指出的那样,有一种情况是不调用Dispose可能导致内存泄漏。有些对象使用Dispose回调来解除长期存在的事件,如果它们保持连接会导致对象驻留在内存中并构成泄漏。总是致电Dispose

的另一个原因

答案 1 :(得分:2)

这完全取决于ServiceController.GetServices()正在做什么。如果它在调用时创建ServiceControllers的新实例,那么它可能会导致内存泄漏,具体取决于它在Dispose方法中需要做什么(ServiceController)。

也就是说,在这种情况下添加'using'无论如何都不会修复它,好像你需要在每个实例上调用dispose(在这种情况下通过'using'隐式),它不会因为它返回它找到一个具有匹配名称的ServiceController。

因此,如果您的第一次迭代找到了匹配的ServiceController,那么所有其他ServiceControllers都不会被处理掉。