سؤال

في طلبي ، لدي الكثير من RichTextboxes التي يتم إنشاؤها ديناميكيًا في وقت التشغيل. أدركت أن التطبيق يحتوي على تسرب ذاكرة ، والذي يحدث بسبب عناصر التحكم في RichTextBox. لإثبات أن الذاكرة تتسرب بسبب التحكم ، كتبت طريقة الاختبار التالية:

for (int i = 0; i < 3000; i++)
        {
            Control rich = new RichTextBox();
            pnl.Content = rich;
        }
GC.Collect();
GC.WaitForPendingFinalizers();

PNL هو contentControl الذي تم الإعلان عنه في رمز XAML.
إذا قمت بتشغيل الكود التالي ، فيمكنك أن ترى أن استخدام الذاكرة ينمو بسرعة.

أي أفكار كيفية حل المشكلة؟ فكرت في إنشاء تجمع كائن ، لكن هذا من شأنه أن يعقد طلبي ، وأفضل تجنب ذلك.


تعديل: لقد أضفت مكالمة إلى جامع القمامة لإثبات أن الكائنات لم يتم جمع القمامة - لا يوجد أي تحسن في استخدام الذاكرة مع وبدون دعوة إلى طريقة جمع GC. لاحظ أن الدعوة rich.Dispose داخل الحلقة يلغي نمو استخدام الذاكرة.

هل كانت مفيدة؟

المحلول

وجدت هذا في مكان آخر ، ويبدو أنه صحيح فيما يتعلق باختباري.

عند إنشاء FlowDocument ، يتم إنشاء كائنات سياق التنسيق باهظة الثمن نسبيًا لها في بنية الهيكل. عند إنشاء FlowDocs متعددة في حلقة ضيقة ، يتم إنشاء structuralCache لكل FlowDoc. دعنا اتصلت بـ gc.collect في نهاية الحلقة ، على أمل استعادة بعض الذاكرة. لدى structuralCache إصدار نهائي يطلق هذا السياق التنسيق ، ولكن ليس على الفور. يحدد Finalizer بشكل فعال العملية لإصدار سياقات في DispatcherPriority.background.

لذا فإن RichTextBox (أو FlowDocument) في حالة عدم تسرب فقط في انتظار سلسلة خلفية للتنظيف. عندما يركض بالضبط من يعرف. أتمنى أن ينفذ هذا للتو طريقة تصرف من شأنها أن تجبر التنظيف على الفور.

نصائح أخرى

هذا ليس مؤشرا على أن التطبيق الخاص بك يحتوي على تسرب ذاكرة ، إنه مؤشر على أن تطبيقك هو باستخدام الكثير من الذاكرة. إنه تسرب إذا كان RichTextBox لا يتم إطلاق الضوابط في مرحلة ما بعد أن سقطت خارج نطاقها (اكتشاف تسرب الذاكرة على الأشياء المدارة أمر صعب للغاية ولا يمكن إثباته).

إن الاعتقاد الخاطئ الشائع بأن كائنًا يسقط خارج النطاق سيؤدي إلى جمع القمامة. هذا فقط يجعله مؤهل التي يتعين جمعها. قد يكون الكائن نظريًا أبداً يتم جمعها حتى ينتهي التطبيق. حقيقة أنه ينمو RichTextBox وليس مع عناصر التحكم الأخرى ، ليس مؤشرا على وجود تسرب ذاكرة في RichTextBox, ، إنه مجرد مؤشر على أنه يستخدم ذاكرة أكبر لكل مثيل أكثر من عناصر التحكم الأخرى. على الرغم من أن هذه المعلومات قد تكون مفيدة ، إلا أنها لا تساعد عند تحديد ما إذا كان هناك تسرب ذاكرة أم لا.

لقد واجهنا نفس المشكلة في WinForms 2.0 واضطررنا إلى شراء تحكم نص غني الطرف الثالث. أعتقد أن Microsoft لم تهتم بإصلاحه ...

هذا إصلاح القضية لي:http://blingcode.blogspot.com/2010/10/memory-leak-with-wpfs-richtextbox.html

أضف أساسا اثنين من سمات كل RichTextBox :) :) isundoenabled = "false"

بخصوص تحريرك:

لقد أضفت مكالمات GC بعد، بعدما الحلقة تنتهي وجميع 3000 RichTextBoxتم إنشاء ES.

على الرغم من أنني أوافق على أنه يبدو من الغريب أن الحلقة السابقة لم يتم تحريرها داخل الحلقة عندما يتم استبدالها بحالة جديدة ، إلا أنها حلقة ضيقة لدرجة أن GC ربما لا تحصل على فرصة "لفعلها" قبل الحلقة ينتهي.

لا أعتقد أنها فكرة جيدة (ولكن يجب أن تكون على ما يرام في رمز الاختبار) ، لكن هل حاولت نقل مكالمات GC داخل الحلقة؟

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