Разблокировать файл, сгенерированный из объекта Bitmap

У меня есть этот метод, чтобы получить миниатюру изображения на диске:

public static BitmapImage GetThumbnail()
{
    var dlg = new OpenFileDialog {Filter = "Imágenes|" + extensionesImagenes};
    var result = dlg.ShowDialog();

    if (result == true)
    {
        var tempFolder = Path.GetTempPath() + "MyTempFolder\\";

        if (!Directory.Exists(tempFolder))
            Directory.CreateDirectory(tempFolder);

        using (var thumbnail = new Bitmap(170, 170))
        {
            using (var gr = Graphics.FromImage(thumbnail))
            {
                gr.SmoothingMode = SmoothingMode.HighQuality;
                gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
                gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
                gr.DrawImage(new Bitmap(dlg.FileName), new Rectangle(0, 0, 170, 170));
            }

            thumbnail.Save(tempFolder + "foto.jpg", ImageFormat.Jpeg);
        }

        return new BitmapImage(new Uri(tempFolder + "foto.jpg"));
    }

    return null;
}

Если запускаю первый раз, то проблем нет. Но когда я запускаю его во второй раз, я получаю исключение «Произошла общая ошибка в GDI +», потому что файл используется моим приложением.

Метод может вызываться несколько раз в зависимости от действий пользователей, и файл должен быть перезаписан. На самом деле, если файл существует, когда я вызываю метод в первый раз, он успешно перезаписывается.

Файл создается методом Save() класса Bitmap, и я не использую какой-либо поток.

Как я могу разблокировать файл?

ТИА

ИЗМЕНИТЬ

Я не использую MemoryStream, потому что мне нужен файл в другом методе: когда пользователь вызывает метод GetThumbnail, миниатюра будет отображаться в StackPanel (миниатюра — это ImageSource StackPanel.)

Позже пользователь может сохранить в базу данных информацию, показанную в форме WPF, включая изображение, и метод, который сохраняет в базу данных, должен прочитать байты из сохраненного изображения.

ИЗМЕНИТЬ 2

Перед использованием миниатюр я использовал этот метод:

public static BitmapImage GetImage()
{
    var dlg = new OpenFileDialog {Filter = "Imágenes|" + extensionesImagenes};
    var result = dlg.ShowDialog();
    return result == true ? new BitmapImage(new Uri(dlg.FileName)) : null;
}

Это работало нормально.

Теперь, когда я использую эскизы, проблема с MemoryStream заключается в том, что я не могу установить Uri для изображения.

Например, я использовал:

imagenNueva = InterfazUtil.GetImage(); // GetImage() is now GetThumbnail()
var rutaFoto = (imagenNueva != null) ? imagenNueva.ToString() : null;

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

В методе GetThumbnail я преобразовал миниатюру изображения в BitmapImage и попытался установить SourceUri и BaseUri с помощью:

новый Uri (диалог.ИмяФайла);

Но когда я вызываю imagenNueva.ToString(), я не получаю действительный Uri.


person Community    schedule 22.07.2013    source источник
comment
когда результат всегда верен? Вы никогда не закрываете свой диалог, поэтому я не знаю, связано ли это с этим (сомневаюсь) (using(var dlg...). Я думаю, дело в том, что .Save не может перезаписывать существующие файлы.   -  person Sayse    schedule 22.07.2013
comment
Спасибо. Диалог закрывается, и условие result == true действительно оценивается, когда пользователь закрывает диалог.   -  person    schedule 22.07.2013
comment
Диалог закрыт да, но не удален   -  person Sayse    schedule 22.07.2013
comment
Диалог не реализует IDisposable. Если я попытаюсь использовать его в операторе использования, я получаю сообщение об ошибке.   -  person    schedule 22.07.2013
comment
Извините, я думал, что все диалоги, открытые с помощью showdialog, нуждаются в удалении. Редактировать Я заметил, что у вас все еще есть растровое изображение, которое не удаляется при рисовании изображения. Если вы выполните свой метод, в какой строке вы получите ошибку   -  person Sayse    schedule 22.07.2013
comment
Строка: thumbnail.Save(tempFolder + ...   -  person    schedule 22.07.2013
comment
Мое последнее предположение было бы вернуть Clone тогда, (BitmapImage().Clone())   -  person Sayse    schedule 22.07.2013
comment
Сделал, все равно ошибка. Но это была хорошая попытка. :)   -  person    schedule 22.07.2013


Ответы (1)


 gr.DrawImage(new Bitmap(dlg.FileName), new Rectangle(0, 0, 170, 170));

Использование такого растрового изображения очень проблематично. Он блокирует файл «dlg.FileName», и сборщик мусора освободит его через некоторое время. Вместо этого вам нужно будет написать это так:

 using (var bmp = new Bitmap(dlg.FileName)) {
     gr.DrawImage(bmp, new Rectangle(0, 0, 170, 170));
 }

Теперь он удаляется сразу после использования, что также снимает блокировку с файла.

Кстати, вы можете полностью избежать написания такого кода, если вместо этого используете MemoryStream. Просто сохраните изображение в MemoryStream, так что вам не нужен файл. Предполагая, что образы не такие большие, или вы можете рассчитывать на работу в 64-битной операционной системе. В противном случае это не причина избегать удаления растровых изображений.

person Hans Passant    schedule 22.07.2013
comment
Спасибо. Я заменил строку используемой версией, но все равно получаю ту же ошибку в той же строке. Я не использую MemoryStream, потому что файл нужен в другом месте. Я отредактирую OP, чтобы объяснить это. - person ; 23.07.2013
comment
Что ж, возможно, это не единственное место, где вы забыли удалить изображение. Вы столько же сказали об этом в этом комментарии. - person Hans Passant; 23.07.2013
comment
Я написал второе редактирование. Надеюсь, это немного прояснит, что я делаю. - person ; 23.07.2013
comment
Ганс, вторую правку я написал очень быстро, и она была немного неясной. Я изменил его, и теперь (надеюсь) он более понятен. Если вы читаете это, возможно, вы можете дать мне подсказку, как обойти мою проблему с помощью MemoryStream. Спасибо за вашу помощь. - person ; 23.07.2013
comment
Немного непонятно - это мягко сказано. Я понятия не имею, что ты делаешь. - person Hans Passant; 23.07.2013
comment
Наверное. Английский не мой родной язык. Извините, что заставил вас тратить ваше время. :( - person ; 23.07.2013