OutOfMemoryException на мобильном устройстве - PullRequest
3 голосов
/ 27 февраля 2009

Я занимаюсь разработкой приложения, которое использует мобильное устройство для фотографирования и отправки его с помощью веб-службы. Но после того, как я сделал 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);
}

Ответы [ 2 ]

5 голосов
/ 27 февраля 2009

Я подозреваю, что вы держитесь за ссылки. В качестве незначительной причины, обратите внимание, что диалоги не располагаются сами по себе при использовании 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 и т. Д., Чтобы гарантировать, что все будет выпущено как можно скорее.

2 голосов
/ 27 февраля 2009

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

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

Приветствия

Nik

...