Как c # обращается с памятью

2

У меня есть класс skImage. Этот класс имеет приватную переменную (с открытым общедоступным свойством)

private Image _capturedImage;  

конструктор этого класса выглядит следующим образом:

   public skImage(Image captured) {

            _capturedImage = captured;

        }

Он также имеет следующий метод:

public bool Invert() {

        Bitmap b = new Bitmap(_capturedImage);

        unsafe {
         //random code not relevant.
        }

        _capturedImage = b;
        b.Dispose();
        return true;
    }

а затем он имеет метод save(), который просто вызывает:

  _capturedImage.Save(_saveFullLocation);

теперь, если я запустил метод инвертирования, а затем попробую вызвать save, он выдает исключение (параметр недействителен). После того, как он отправил это исключение, похоже, что я избавляюсь от изображения. Я вижу, что я удаляю "b" после метода инвертирования.

Мой вопрос в том, что когда я делаю _capturedImage = b, это означает, что обе переменные теперь содержат одну ссылку на объект? Я этого не хочу. Я хочу, чтобы b был уничтожен, чтобы освободить память, чтобы GC мог ее собрать. Как передать b в _capturedImage и уничтожить b.

спасибо

Теги:
pass-by-reference

5 ответов

3
Лучший ответ

означает ли это, что обе переменные теперь содержат одну ссылку на объект?

Да. Тем не менее, ссылка является лишь ссылкой - она ​​не стоит много памяти.

Я хочу, чтобы b был уничтожен

Вы не можете уничтожить ссылку - вы можете уничтожить сам объект.

Вместо удаления b вы должны написать:

_capturedImage.Dispose();
_capturedImage = b;
  • 0
    будет ли это означать, что когда b выходит за пределы области действия (т. е. метод завершен), GC соберет b и освободит всю связанную с ним память?
  • 0
    @masfenix - ссылка b создается в кадре стека метода Invert - когда этот метод возвращается, b больше не будет существовать. Однако объект, на который ссылается b (растровое изображение), все еще будет существовать в куче (до тех пор, пока не будет собран мусор).
Показать ещё 2 комментария
2

_capturedImage и b - ссылки на один и тот же базовый объект. Вызов b.Dispose(); также будет распоряжаться _capturedImage, так как они являются как ссылками, которые указывают на один и тот же блок данных. Когда b выходит за рамки (то есть, когда возвращается Invert), b прекратит существование, но GC не будет собирать данные, поскольку _capturedImage все еще указывает на него.

1

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

Таким образом, если у вас есть какое-либо поведение, связанное с модификацией переменной хранения, вы избегаете "мерцания". Это обычно используется при двойной буферизации;

public bool Invert() 
{
    //this will create a clone of _captureImage, so you effectivly have 2 Bitmaps at that point
    Bitmap b = new Bitmap(_capturedImage); 

    unsafe 
    {
     //random code not relevant.
    }

    var old = _capturedImage; //store old reference

    //assign, any events will seemlesly transition from the old to the new Bitmap
    _capturedImage = b; 
    old.Dispose(); //get rid of the old Bitmap

    return true;
}
0

Как уже упоминалось, вы делаете b и _capturedImage, указываете на один и тот же объект, поэтому, когда вы удаляете b, _capturedImage тоже дипидируется.

Я не вижу необходимости называть Dipose() здесь. Переменная объявляется в области действия функции, поэтому она не будет иметь никаких ссылок, и GC автоматически очистит ее.

Фактически, я даже не вижу необходимости в переменной "b". Почему бы вам просто не использовать '_capturedImage' во всей функции и сохранить вещи просто?

-3

image.Clone()

Вам придется снова нанести результат на ваш тип данных, так как Clone() возвращает объект System.Object.

Изменить: я, должно быть, неправильно понял проблему. Я думал, что вы хотите иметь изображение, которое не может быть удалено кодом в другом месте. Пока вы сообщаете ссылки на один и тот же образ в памяти, все остальные, кто знает об этом изображении, могут распоряжаться им, эффективно навязывая вас. Клонируя изображение, вы гарантируете, что никто другой (или какой-либо другой код, который вы написали) не сможет его уничтожить.

  • 0
    что мне клонировать? вместо _capturedImage = b, я должен сделать _capturedImage = b.clone (); ??
  • 0
    Зачем клонировать изображение?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню