2009-02-27 6 views
3

Ich entwickle eine Anwendung, die ein mobiles Gerät verwendet, um ein Foto zu machen und es über einen Webservice zu senden. Aber nachdem ich 4 Fotos gemacht habe, bekomme ich einen OutOfMemoryException im folgenden Code. Ich habe versucht, GC.Collect() anzurufen, aber es half auch nicht. Vielleicht könnte jemand hier einen Rat geben, wie man mit diesem Problem umgeht.OutOfMemoryException auf mobilem Gerät

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

Die Funktion wird von einem Event-Handler aufgerufen wird:

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

Antwort

5

Ich vermute, Sie auf Referenzen halten. Als kleine Ursache ist zu beachten, dass Dialoge sich bei der Verwendung von ShowDialog nicht entfernen, Sie sollten also den Dialog using haben (obwohl ich erwarte, dass GC immer noch ein nicht disponiertes, aber nicht referenziertes Dialogfeld sammelt).

Ebenso sollten Sie wahrscheinlich using das Bild sein, aber wieder: nicht sicher, ich würde erwarten, dass dies zu machen oder zu brechen; einen Versuch wert, aber ...

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

ich auch ein wenig vorsichtig von dem CutBitmap etc sein würde, um sicherzustellen, dass die Dinge so schnell wie möglich freigegeben werden.

+1

Ich würde Ihren Code leicht ändern - wo es das Bild picturebox setzt, würde ich jedes vorhandene Bild zuerst, a la Wenn (_pictureBox.Image! = Null) _pictureBox.Image.Dispose(). – ctacke

2

Ihr mobiles Gerät in der Regel keine Speicher auf der Festplatte Option Swapping hat, so da Sie wählen Ihre Bilder als Bitmaps im Speicher speichern eher Als Dateien auf der Festplatte verbrauchen Sie schnell den Speicher Ihres Telefons. Ihre Zeile "new Bitmap()" reserviert einen großen Teil des Speichers, so dass es sehr wahrscheinlich ist, die Ausnahme dort zu werfen. Ein weiterer Anwärter ist Ihr Camera.ImageToByteArray, das eine große Menge an Speicher zuweist. Dies ist wahrscheinlich nicht groß, was Sie mit Ihrem Computer gewohnt sind, aber für Ihr Handy ist das riesig

Versuchen Sie, die Bilder auf der Festplatte zu halten, bis Sie sie verwenden, d. H. Bis sie an den Webservice gesendet werden. Verwenden Sie die integrierten Steuerelemente, um sie anzuzeigen. Sie sind wahrscheinlich die Speichereffizienz, und Sie können sie normalerweise auf die Bilddateien verweisen.

Prost

Nik

+0

Es gibt kein "normalerweise" dazu. CE hat keine Möglichkeit, auf die Festplatte zu wechseln, also tut es kein Gerät. – ctacke

Verwandte Themen