Question

Je développe une application qui utilise un appareil mobile pour prendre une photo et l'envoyer à l'aide d'un webservice. Mais je suis après que j'ai pris 4 photos reçois un OutOfMemoryException dans le code ci-dessous. J'ai essayé d'appeler GC.Collect() mais il n'a pas aidé non plus. Peut-être que quelqu'un ici pourrait être me donner un conseil comment gérer ce problème.

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

La fonction est appelée par un gestionnaire d'événement:

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);
}
Était-ce utile?

La solution

Je suppose que vous tenez sur des références. En tant que cause mineure, notez que les dialogues ne se disposent lors de l'utilisation ShowDialog, vous devriez donc être using la boîte de dialogue (bien que je me attends GC de recueillir encore un dialogue, mais non non aliéné référencé).

De même, vous devriez probablement using l'image, mais encore une fois: pas sûr que je m'y attendais à faire ou ça casse; la peine d'essayer, mais ...

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

Je voudrais aussi être un peu prudent du CutBitmap etc, afin d'assurer que les choses sont libérés dès que possible.

Autres conseils

Votre appareil mobile n'a généralement pas de permutation mémoire à l'option de disque, donc, puisque vous choisissez de stocker vos images bitmaps en mémoire plutôt que des fichiers sur le disque, vous consommez rapidement la mémoire de votre téléphone. Votre « nouvelle Bitmap () » ligne alloue une grande partie de la mémoire, il est donc très probable de jeter l'exception là. Un autre concurrent est votre Camera.ImageToByteArray qui allouera une grande quantité de mémoire. Ceci est probablement pas grand à ce que vous êtes habitué avec votre ordinateur, mais pour votre mobile de c'est gigantesque

Essayez de garder les images sur le disque jusqu'à ce que vous les utilisez, à savoir que de les envoyer au webservice. Pour les afficher, utilisez vos contrôles intégrés, ils sont probablement les plus efficace de la mémoire et vous pouvez généralement les pointer vers les fichiers d'image.

Vive

Nik

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top