Вопрос

Я разрабатываю приложение, которое использует мобильное устройство для фотографирования и отправки его с помощью веб-сервиса.Но после того, как я сделал 4 фотографии, я получаю OutOfMemoryException в коде ниже.Я попробовал позвонить GC.Collect() но и это не помогло.Может быть, кто-нибудь здесь сможет дать мне совет, как справиться с этой проблемой.

public static Bitmap TakePicture()
{
    var dialog = new CameraCaptureDialog
    {
        Resolution = new Size(1600, 1200),
        StillQuality = CameraCaptureStillQuality.Default
    };

    dialog.ShowDialog();

    // If the filename is empty the user took no picture
    if (string.IsNullOrEmpty(dialog.FileName))
       return null;

    // (!) The OutOfMemoryException is thrown here (!)
    var bitmap = new Bitmap(dialog.FileName);

    File.Delete(dialog.FileName);

    return bitmap;
}

Функция вызывается обработчиком событий:

private void _pictureBox_Click(object sender, EventArgs e)
{
    _takePictureLinkLabel.Visible = false;

    var image = Camera.TakePicture();
    if (image == null)
       return;

    image = Camera.CutBitmap(image, 2.5);
    _pictureBox.Image = image;

    _image = Camera.ImageToByteArray(image);
}
Это было полезно?

Решение

Я подозреваю, что вы держитесь за ссылки.В качестве незначительной причины обратите внимание, что диалоги не удаляются при использовании ShowDialog, так что ты должен быть using диалог (хотя я ожидаю, что GC все равно соберет нераспространенный, но не имеющий ссылок диалог).

Аналогично, вам, вероятно, следует быть using изображение, но опять же:не уверен, что ожидаю, что это станет решающим фактором;хотя попробовать стоит...

public static Bitmap TakePicture()
{
    string filename;
    using(var dialog = new CameraCaptureDialog
    {
        Resolution = new Size(1600, 1200),
        StillQuality = CameraCaptureStillQuality.Default
    }) {

        dialog.ShowDialog();
        filename = dialog.FileName;
    }    
    // If the filename is empty the user took no picture
    if (string.IsNullOrEmpty(filename))
       return null;

    // (!) The OutOfMemoryException is thrown here (!)
    var bitmap = new Bitmap(filename);

    File.Delete(filename);

    return bitmap;
}

private void _pictureBox_Click(object sender, EventArgs e)
{
    _takePictureLinkLabel.Visible = false;

    using(var image = Camera.TakePicture()) {
        if (image == null)
           return;

        image = Camera.CutBitmap(image, 2.5);
        _pictureBox.Image = image;

        _image = Camera.ImageToByteArray(image);
    }
}

Я бы также был немного осторожен с CutBitmap и т. д., чтобы гарантировать, что все будет выпущено как можно скорее.

Другие советы

Ваше мобильное устройство обычно не имеет возможности подкачки памяти на диск, поэтому, поскольку вы предпочитаете хранить изображения в виде растровых изображений в памяти, а не в виде файлов на диске, вы быстро расходуете память своего телефона.Ваша строка «new Bitmap()» выделяет большой кусок памяти, поэтому весьма вероятно, что там будет выдано исключение.Еще одним претендентом является ваш Camera.ImageToByteArray, который будет выделять большой объем памяти.Вероятно, это не так уж и много по сравнению с тем, к чему вы привыкли на своем компьютере, но для вашего мобильного телефона это гигантская цифра.

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

Ваше здоровье

Ник

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top