2009-02-27 9 views
3

Je développe une application qui utilise un périphérique mobile pour prendre une photo et l'envoyer à l'aide d'un service Web. Mais après avoir pris 4 photos, j'obtiens un OutOfMemoryException dans le code ci-dessous. J'ai essayé d'appeler GC.Collect() mais cela n'a pas aidé non plus. Peut-être que quelqu'un ici pourrait me donner un conseil sur la façon de gérer ce problème.OutOfMemoryException sur le périphérique mobile

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énements:

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

Répondre

5

Je suppose que vous tenez sur des références. Comme une cause mineure, notez que les boîtes de dialogue ne se disposent pas lorsque vous utilisez ShowDialog, donc vous devriez être le using le dialogue (bien que je m'attendrais à ce que le GC collecte toujours une boîte de dialogue non-référencée mais non-référencée).

De même, vous devriez probablement être using l'image, mais encore une fois: je ne suis pas sûr que je m'attendrais à faire ou à ne pas faire; 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.

+1

Je modifierais légèrement votre code - où il définit l'image de la zone d'image, je disposerais de toute image existante d'abord, un si la (_pictureBox.Image! = Null) _pictureBox.Image.Dispose(). – ctacke

2

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 les fichiers sur le disque, vous consommez rapidement la mémoire de votre téléphone. Votre "nouvelle ligne Bitmap()" alloue un gros morceau de mémoire, il y a donc fort à parier qu'il y aura une exception. Un autre concurrent est votre Camera.ImageToByteArray qui va allouer une grande quantité de mémoire. Essayez de conserver les images sur le disque jusqu'à ce que vous les utilisiez, c'est-à-dire jusqu'à ce que vous les envoyiez au WebService.

Essayez de conserver les images sur le disque jusqu'à ce que vous les utilisiez. Pour les afficher, utilisez vos contrôles intégrés, ils sont probablement les plus efficaces pour la mémoire et vous pouvez généralement les pointer vers les fichiers image.

Vive

Nik

+0

Il n'y a pas de «manière habituelle». CE n'a aucune disposition pour l'échange sur disque, donc aucun appareil ne le fait. – ctacke