Domanda

Sto sviluppando un'applicazione che utilizza un dispositivo mobile per scattare una foto e inviarla con un webservice. Ma dopo che ho preso 4 foto sto ottenendo un OutOfMemoryException nel seguente codice. Ho provato a chiamare GC.Collect(), ma non ha aiutato neanche. Forse qualcuno qui potrebbe essere darmi un consiglio su come gestire questo problema.

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 funzione viene chiamata da un gestore di eventi:

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);
}
È stato utile?

Soluzione

Ho il sospetto che si sta trattenendo i riferimenti. Come una causa minore, si noti che le finestre di dialogo non dispongono stessi quando si utilizza ShowDialog, così si dovrebbe essere using finestra (anche se mi sarei aspettato GC per raccogliere ancora una undisposed ma dialogo non si fa riferimento).

Allo stesso modo, si dovrebbe probabilmente essere using l'immagine, ma ancora una volta: non sono sicuro mi aspetto che questo make-or-break; la pena di provare, anche se ...

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

Mi piacerebbe anche essere un po 'cauto del CutBitmap ecc, al fine di garantire che le cose vengono rilasciati al più presto.

Altri suggerimenti

Il dispositivo cellulare di solito non ha alcuna memoria swap opzione disco, in modo da quando si sceglie di memorizzare le immagini come bitmap in memoria piuttosto che i file su disco, si consumano rapidamente la memoria del telefono. La vostra linea "new Bitmap ()" assegna un grande pezzo di memoria, quindi è molto probabile che generare l'eccezione c'è. Un altro concorrente è il tuo Camera.ImageToByteArray che attribuisce una grande quantità di memoria. Questo probabilmente non è grande per quello che siete abituati a con il computer, ma per il vostro cellulare questo è gigantesco

Prova a tenere le immagini su disco fino a quando non li si usa, vale a dire fino a quando inviarli al webservice. Per visualizzarli, utilizzare i controlli integrati, sono probabilmente il più efficiente della memoria e di solito è possibile indicare i file di immagine.

Saluti

Nik

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top