Как GC и IDispose работают в C #? - PullRequest
1 голос
/ 23 апреля 2009

Я помню, что я загружал изображения, передавая их из сети прямо в растровое изображение. закройте поток, верните растровое изображение и удерживайте его в элементе управления изображением.

Я исключил, когда я сделал = loadPicture (), первое растровое изображение было бы освобождено, как умный указатель сделал бы в C ++. Но это не так, и я потреблял много барана, пока не позвонил утилизировать. Итак, мой вопрос.

Как GC и Dispose способные объекты работают в C #? и почему он не реализован как smart_ptr?

Ответы [ 4 ]

8 голосов
/ 23 апреля 2009

Ссылки не являются умными указателями. Разрешение ссылочной переменной выйти из области видимости, заменить ее другим значением и / или установить для нее значение null, все делают ровно ничего .

Это просто часть дизайна CLI / GC ...

Сборщик мусора (GC) будет запускать при необходимости и должен очищать используемую управляемую память и (если предоставляется финализатор) также любые неуправляемые ресурсы. Но для детерминированной очистки: вот и вся цель IDisposable. Ваша работа заключается в Dispose() таких объектах, когда вы покончили с ними - либо через using, либо передав его кому-то еще, что принимает на себя эту ответственность (обычно, например, для потоков / читателей и т.д.).

using (StreamReader reader = new StreamReader(myfile)))
{
   ...
}
2 голосов
/ 23 апреля 2009

GC запускается, когда среда выполнения чувствует, что это необходимо.

Основное правило: когда вы используете тип Disposable (IDispose), вы (как программист) должны как можно скорее высвободить ресурсы, используемые этим типом, вызвав Dispose, когда вам больше не нужно тип. Например, когда вы читаете файл, вы закрываете его, как только закончите читать. (В этом случае вызов close также вызовет dispose).

1 голос
/ 23 апреля 2009

Вы должны вызвать Dispose explicity для любого объекта, реализующего IDisposable, в противном случае ваши неуправляемые ресурсы не будут утилизироваться . Если вы не хотите называть это явным, тогда вы должны переопределить метод Finalize для вызова метода Dispose - вот почему вы будете часто видеть это:

 class MyClass : IDisposable
 {
    ...

    ~MyClass()
    { 
       this.Dispose(false);
    }

    public void Dispose()
    {
       this.Dispose(true);
       GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        { /* dispose managed stuff also */ }

        /* but dispose unmanaged stuff always */
    }
 }
0 голосов
/ 23 апреля 2009

smart_ptr подсчитаны. Хотя это позволяет детерминистически высвобождать свои ресурсы, когда на них больше нет ссылок из какого-либо кода, у них действительно есть свои собственные проблемы: назначение ссылок всегда требует обновления счетчика, циклические ссылки не удаляются автоматически, вызывая утечки памяти, диспетчер памяти вызывается чаще.

ГХ в .NET - это быстрый сборщик. Он запускается в любое время, когда он чувствует, что память должна быть освобождена (как правило, вызвано некоторыми условиями использования памяти, но не детерминированно), и начинается с создания списка всех активных ссылок в системе (включая ссылки в регистрах ЦП, вложенные ссылки и т. Д. .). Это работает, поскольку мы находимся в управляемой среде, где вы не можете выполнять арифметику указателей и т. Д. - система может отслеживать все ссылки. После того, как список живых ссылок был создан, он в основном освобождает всю память, которая больше не используется. Конечно, это всего лишь базовый набросок, для эффективности и управления неуправляемыми ресурсами есть нечто большее, например, генерация объектов, финализаторы и т. Д., Но это не важно для базового понимания того, как это работает.

Интерфейс IDisposable используется для реализации одноразового шаблона, который помогает, когда вы работаете с объектами, которые должны быть расположены детерминированным способом. Шаблон таков, что Dispose () вызывается явно, когда объект больше не нужен, поэтому освобождает неуправляемые ресурсы или закрывает дескрипторы и т. Д., Но не освобождает свою память. Это будет сделано GC позже, но не имеет значения, что это произойдет позже, потому что детерминированное освобождение ресурсов уже выполнено.

...