Pergunta

Estou desenvolvendo um aplicativo que usa um dispositivo móvel para tirar uma foto e enviá-lo usando um webservice. Mas depois que eu tomei 4 fotos que eu estou recebendo um OutOfMemoryException no código abaixo. Tentei ligar GC.Collect() mas não quer ajudar. Talvez alguém aqui poderia ser dar-me um conselho como lidar com este 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;
}

A função é chamada por um manipulador de eventos:

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);
}
Foi útil?

Solução

Eu suspeito que você está segurando em referências. Como uma causa menor, nota que os diálogos não deite-se ao usar ShowDialog, então você deve ser using de diálogo (embora eu esperaria GC ainda cobrar um diálogo undisposed mas não referenciada).

Da mesma forma, você provavelmente deve ser using a imagem, mas mais uma vez: não tenho certeza eu esperaria isso para tornar-or-break; vale a pena tentar, embora ...

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

Eu também estaria um pouco cauteloso do CutBitmap etc, para garantir que as coisas são liberados o mais rápido possível.

Outras dicas

O seu dispositivo móvel normalmente não tem qualquer memória trocando opção de disco para, por isso desde que você escolher para armazenar suas imagens como bitmaps na memória, em vez de arquivos no disco, você consumir rapidamente a memória do seu telefone. Seu "novo Bitmap ()" aloca linha de um grande pedaço de memória, por isso é muito provável que lançar a exceção lá. Outro candidato é o seu Camera.ImageToByteArray que irá alocar uma grande quantidade de memória. Isso provavelmente não é grande para o que você está acostumado com o seu computador, mas para o seu dispositivo móvel Esta é gigantesca

Tente manter as imagens no disco até que você usá-los, ou seja, até enviá-los para o webservice. Para exibi-los, use o built-in controles, eles são provavelmente o mais eficiente de memória e, geralmente, você pode apontá-los para os arquivos de imagem.

Felicidades

Nik

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top