2010-01-15 6 views
2

У меня есть класс skImage. Этот класс имеет приватный переменный (с общественной собственностью, которая обнажает его)Как C# обрабатывает память

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); 

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

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

благодаря

ответ

3

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

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

Я хочу б быть уничтожены

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

Вместо утилизации б вы должны написать:

_capturedImage.Dispose(); 
_capturedImage = b; 
+0

будет означать, когда b выходит за рамки (то есть, закон закончен) GC собирает b и освобождает всю связанную с ним память? – masfenix

+0

@masfenix - Ссылка b создается в кадре стека метода Invert - когда этот метод возвращается, b больше не будет существовать. Однако объект, к которому относится b (битмап), все еще будет существовать в куче (пока не будет собран мусор). – mbeckish

+0

Чтобы добавить комментарий к mbeckish, этот объект не будет собирать мусор (ну, не сейчас), потому что битмап по-прежнему указывается _capturedImage. – Brian

-2

image.Clone()

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

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

+0

Что делать, чтобы клонировать? вместо _capturedImage = b, должен ли я делать _capturedImage = b.clone(); ?? – masfenix

+0

Почему клонирование изображения? – Matthias

+1

-1: Клонирование объекта и утилизация оригинала почти наверняка глупо. – Brian

2

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

0

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

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

Фактически, я даже не вижу необходимости в переменной «b». Почему бы вам просто не использовать «_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; 
} 
Смежные вопросы