سؤال

أنا أستخدم العديد من السلوكيات المزيج والمشغلات على التحكم في Silverlight. أتساءل عما إذا كانت هناك أي آلية لفصل أو ضمان تلقائيًا إلى أن OnDetaching () يتم استدعاؤه لسلوك أو تشغيل عند عدم استخدام التحكم (أي إزالته من الشجرة المرئية).

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

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

public void DetachBehaviors()
{
     foreach (var behavior in Interaction.GetBehaviors(this.LayoutRoot))
     {
          behavior.Detach();
     }

     //continue detaching all known problematic behaviors on the control....
}
هل كانت مفيدة؟

المحلول

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

يتم تحقيق ذلك من خلال تنفيذ نمط الوسيط. المفهوم هو أنك لا تعطي الكائن طويل الأجل مندوبًا مع إشارة إلى Behaviour, ، بدلاً من ذلك ، تقوم بإنشاء فئة الوسيط باعتباره يعلق الوسيط على حدث الكائنات الطويلة العمر ويحمل أ ضعف للسلوك. عندما يطلق الكائن منذ فترة طويلة الحدث ، يتحقق الوسيط من أن WeakReference لا يزال على قيد الحياة ، إذا كان الأمر كذلك يتصل بالطريقة لتمرير الحدث. إذا عندما يحدث الحدث ، يجد الوسيط أن WeakReference لم يعد على قيد الحياة ، فإنه يفصل معالج الحدث من الكائن الطويل.

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

لحسن الحظ ، لا تضطر إلى بناء هذه الأشياء بنفسك قام الآخرون بذلك بالفعل. يطلق عليه WeakEventListener. هذه المدونة: تسليط الضوء على مساهمة "ضعيفة" ؛ التحسينات تجعل منع تسرب الذاكرة مع WeakeventListener أسهل! لديه مجموعة ممتازة من الروابط حول هذا الموضوع.

نصائح أخرى

يوست فان شايك يوفر طريقة بديلة لتنظيف المراجع من السلوكيات المرفقة ، مع تجنب المشكلة مع تسرب الذاكرة. يعتمد ذلك على القيام بأعمال التنظيف باستخدام مندوبي الأحداث المحملة والتفريغ من AssociatedObject.

كما أنه يقدم رمزًا لتوليد كعب للسلوكيات المرفقة.

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