سؤال

في C # /. Net، هل هناك أي طريقة للحصول على إشعار قبل أن يشير الكائن إلى إشارة ضعيفة مدمر؟ في الأساس، أريد أن أسمح بجمع كائن، ولكن القيام بشيء ما قبل تدمير الكائن، دون تعديل التعليمات البرمجية لإضافة المدمرين (نظرا لأنني لن أعرف بالضبط ما يمكن مقاضات أنواع الكائنات بالضبط.

شكرا يا روبرت

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

المحلول

.NET 4.0 لديه الحل الذي تحتاجه: شرطي. وبعد فيما يلي برنامج قصير يدل على الفكرة. (ناقش هنا كذلك)

using System;
using System.Runtime.CompilerServices;

namespace GCCollectNotification
{
    class ObjectToWatch { }

    class Notifier
    {
        public object ObjectToWatch { get; set; }
        ~Notifier() { Console.WriteLine("object is collected"); }
    }

    class Program
    {
        private ConditionalWeakTable<object, Notifier> map
            = new ConditionalWeakTable<object, Notifier>();

        public void Test()
        {
            var obj = new ObjectToWatch();
            var notifier = map.GetOrCreateValue(obj);
            notifier.ObjectToWatch = obj;
        }

        static void Main(string[] args)
        {
            new Program().Test();

            GC.Collect();
            GC.WaitForPendingFinalizers();

            // "object is collected" should have been printed by now

            Console.WriteLine("end of program");
        }
    }
}

نصائح أخرى

لا توجد طريقة لتحقيق هذه الوظيفة.

بعد قليل من التكهنات، لا أعتقد أنه من الممكن تنفيذ ميزة بالطريقة التي تصفها.

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

يمكنك أن ترى كيف لا يمكن رفع المرة الثانية حول الحدث لأنه سيؤدي إلى كائنات غير قابلة للتحصيل.

سيكون إساءة استخدام التسمية للمطالبة تم رفع هذا الحدث قبل جمع كائن. ببساطة لأن أي معالج يمكن أن يمنع ذلك من جمعها من خلال إنشاء إشارة جديدة إلى الكائن. بدلا من ذلك، يجب أن تكون "ObjectMayBeabouttObeColled". ربما لن يمنحك هذا السلوك الذي تبحث عنه.

لا يمكنك القيام بذلك. ومع ذلك، ما يمكنك القيام به هو مشاهدته عندما يقترب GC (هناك واجهات برمجة تطبيقات GC جديدة في CLR V3.5SP1 تتيح لك القيام بذلك، GCNotifications)

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

ما هي مشكلة التصميم الفعلية التي تريد حلها؟ قد تكون هناك طريقة أفضل.

لما تصفه، ستكون النهج النهائي طريقة أفضل.

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

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

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

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