У меня есть класс 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.
спасибо
означает ли это, что обе переменные теперь содержат одну ссылку на объект?
Да. Тем не менее, ссылка является лишь ссылкой - она не стоит много памяти.
Я хочу, чтобы b был уничтожен
Вы не можете уничтожить ссылку - вы можете уничтожить сам объект.
Вместо удаления b вы должны написать:
_capturedImage.Dispose();
_capturedImage = b;
_capturedImage и b - ссылки на один и тот же базовый объект. Вызов b.Dispose(); также будет распоряжаться _capturedImage, так как они являются как ссылками, которые указывают на один и тот же блок данных. Когда b выходит за рамки (то есть, когда возвращается Invert), b прекратит существование, но GC не будет собирать данные, поскольку _capturedImage все еще указывает на него.
Общее правило, когда вам нужно создать новый 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;
}
Как уже упоминалось, вы делаете b и _capturedImage, указываете на один и тот же объект, поэтому, когда вы удаляете b, _capturedImage тоже дипидируется.
Я не вижу необходимости называть Dipose() здесь. Переменная объявляется в области действия функции, поэтому она не будет иметь никаких ссылок, и GC автоматически очистит ее.
Фактически, я даже не вижу необходимости в переменной "b". Почему бы вам просто не использовать '_capturedImage' во всей функции и сохранить вещи просто?
image.Clone()
Вам придется снова нанести результат на ваш тип данных, так как Clone() возвращает объект System.Object.
Изменить: я, должно быть, неправильно понял проблему. Я думал, что вы хотите иметь изображение, которое не может быть удалено кодом в другом месте. Пока вы сообщаете ссылки на один и тот же образ в памяти, все остальные, кто знает об этом изображении, могут распоряжаться им, эффективно навязывая вас. Клонируя изображение, вы гарантируете, что никто другой (или какой-либо другой код, который вы написали) не сможет его уничтожить.