سؤال

أقوم بتطوير تطبيق يستخدم جهاز محمول لالتقاط صورة وإرساله باستخدام WebService. ولكن بعد أخذت 4 صور أحصل على OutOfMemoryException في الكود أدناه. حاولت الاتصال GC.Collect() لكنها لم تساعد أيضا. ربما شخص ما هنا يمكن أن تعطيني نصيحة كيفية التعامل مع هذه المشكلة.

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

وتسمى الوظيفة بواسطة معالج الأحداث:

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);
}
هل كانت مفيدة؟

المحلول

أظن أنك تمسك بالمراجع. كسبب بسيط، لاحظ أن مربعات الحوار لا تتخلص من أنفسهم عند استخدام ShowDialog, ، لذلك يجب أن تكون using الحوار (على الرغم من أنني أتوقع أن لا يزال GC لجمع مربع حوار غير واضح ولكن غير مرجعي).

وبالمثل، ربما يجب أن تكون using الصورة، ولكن مرة أخرى: غير متأكد من أنني أتوقع أن يحدث هذا أو كسر؛ يستحق المحاولة، على الرغم من ...

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

سأكون أيضا حذرا قليلا من CutBitmap إلخ، لضمان إصدار الأمور في اسرع وقت ممكن.

نصائح أخرى

عادة لا يحتوي جهازك المحمول على أي خيار تبديل الذاكرة إلى القرص، لذلك نظرا لأنك تختار تخزين صورك كبالغة مجانية في الذاكرة بدلا من الملفات الموجودة على القرص، فإنك تستهلك بسرعة ذاكرة هاتفك. تخصص خط "New Bitmap ()" جزء كبير من الذاكرة، لذلك من المحتمل جدا أن يرمي الاستثناء هناك. منافس آخر هو الكاميرا. magetobytearray التي ستخصص كمية كبيرة من الذاكرة. ربما هذا ليس كبيرا لما اعتدت على جهاز الكمبيوتر الخاص بك، ولكن من أجل هاتفك المحمول عملاق

حاول الحفاظ على الصور على القرص حتى تستخدمها، أي حتى إرسالها إلى WebService. لعرضها، استخدم عناصر التحكم المدمجة الخاصة بك، فهي ربما تكون أكثر كفاءة الذاكرة ويمكن أن تشير إليها عادة إلى ملفات الصور.

هتافات

نيك

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top