IDisposable: утечки памяти - PullRequest
       13

IDisposable: утечки памяти

3 голосов
/ 07 ноября 2011

В настоящее время я делаю обзор приложения на C #, в котором вижу следующее:

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

В этом ответе Хенк сказал, что неиспользование Dispose() (или using) не приведет к утечкам памяти, true или false?

Могу ли я сохранить предыдущий код, есть он или я должен написать что-то вроде:

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 ]

6 голосов
/ 07 ноября 2011

Правильно написанный объект не должен вызывать утечку памяти, если его метод Dispose не вызывается. В наши дни объект .Net, управляющий неуправляемыми ресурсами, должен делать это через экземпляр SafeHandle . Это обеспечит освобождение собственной памяти, даже если Dispose не вызывается.

Однако объекты, которые написаны неправильно, могут вызвать утечку памяти, если не вызывается Dispose. Я видел много примеров таких объектов.

В целом, если вы используете экземпляр IDisposable, которым вы владеете, вы всегда должны вызывать Dispose. Даже если объект написан правильно, в вашу пользу неуправляемые ресурсы будут очищаться раньше, а не позже.

EDIT

Как отметил Джеймс в комментариях, есть один случай, когда не вызов Dispose может вызвать утечку памяти. Некоторые объекты используют обратный вызов Dispose для отсоединения от долгоживущих событий, которые, если они останутся подключенными, приведут к тому, что объект окажется в памяти и станет утечкой. Еще одна причина всегда звонить Dispose

2 голосов
/ 07 ноября 2011

Все зависит от того, что делает ServiceController.GetServices ().Если он создает новые экземпляры ServiceControllers при его вызове, то это может вызвать утечку памяти в зависимости от того, что ему нужно сделать (ServiceController) в его методе Dispose.

При этом добавляется «using» вв этом случае это все равно не будет исправлено, так как если бы вам DID нужно было вызывать dispose (неявно через 'using' в данном случае) для каждого экземпляра, он НЕ БУДЕТ возвращаться всякий раз, когда обнаруживает ServiceController с совпадающим именем.

Поэтому, если ваша первая итерация обнаружит соответствующий ServiceController, все остальные ServiceController не будут удалены в любом случае.

...