IDisposable:内存泄漏

本文关键字:泄漏 内存 IDisposable | 更新日期: 2023-09-27 18:13:49

我目前正在做一个c#应用程序的审查,其中我看到:

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

在这个回答中,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)的风险是什么?

IDisposable:内存泄漏

如果没有调用Dispose方法,正确编写的对象不应该导致内存泄漏。现在,控制非托管资源的。net对象应该通过SafeHandle实例来实现。这将确保即使没有调用Dispose,本机内存也会被释放。

然而,如果没有调用Dispose,那么没有正确编写的对象很可能会产生内存泄漏。我见过很多这样的例子。

一般来说,如果你使用自己拥有的IDisposable实例,你应该总是调用Dispose。即使对象被正确写入,非托管资源被更早而不是更晚地清理也是对您有利的。

编辑

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

的另一个原因

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

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

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