কেউ এই চূড়ান্ত আচরণ ব্যাখ্যা করতে পারেন

যদিও 'তদন্ত' চূড়ান্তকরণ (পড়া: মূঢ় জিনিস চেষ্টা) আমি কিছু অপ্রত্যাশিত আচরণ জুড়ে stumbled (অন্তত আমার কাছে)।

আমি ফাইনালাইজেশন পদ্ধতিটি না বলে আশা করি, তবে এটি দুবার বলা হয়

class Program
{
    static void Main(string[] args)
    {
       //The MyClass type has a Finalize method defined for it
       //Creating a MyClass places a reference to obj on the finalization table.
        var myClass = new MyClass();

       //Append another 2 references for myClass onto the finalization table.
        System.GC.ReRegisterForFinalize(myClass);
        System.GC.ReRegisterForFinalize(myClass);
       //There are now 3 references to myClass on the finalization table.

        System.GC.SuppressFinalize(myClass);
        System.GC.SuppressFinalize(myClass);
        System.GC.SuppressFinalize(myClass);

       //Remove the reference to the object.
        myClass = null;

       //Force the GC to collect the object.
        System.GC.Collect(2, System.GCCollectionMode.Forced);

       //The first call to obj's Finalize method will be discarded but
       //two calls to Finalize are still performed.
        System.Console.ReadLine();
    }
}

class MyClass
{
    ~MyClass()
    {
        System.Console.WriteLine("Finalise() called");
    }
}

যে কেউ এই আচরণ ইচ্ছাকৃত কিনা এবং ব্যাখ্যা যদি ব্যাখ্যা করতে পারে কেন?

এই উপরের কোডটি x86 ডিবাগ মোডে কম্পাইল করা হয়েছে এবং CLR v4 এ চলছে।

অনেক ধন্যবাদ

6

4 উত্তর

আমি জানি না বিদ্বেষপূর্ণ আচরণ কী। যাইহোক, যেহেতু আপনি পদ্ধতির নথির ব্যবহার লঙ্ঘন করছেন, তাই কিছু ঘটতে পারে। ReregisterForFinalize জন্য ডকুমেন্টেশন বলেছেন:

নির্দিষ্ট যন্ত্রের জন্য সিস্টেমটি চূড়ান্তকরণকারীকে অনুরোধ করে যার জন্য SuppressFinalize পূর্বে বলা হয়েছে।

আপনি পূর্বে ReregisterForFinalize বলা হয় আগে আপনি SuppressFinalize কল না। ডকুমেন্টেশন যে পরিস্থিতিতে ঘটতে না বলে, এবং আসলে, দৃশ্যত সত্যিই অদ্ভুত কিছু ঘটে।

দুর্ভাগ্যবশত, একই ডকুমেন্টেশনের পৃষ্ঠায় এমন একটি উদাহরণ দেখা যাচ্ছে যা কোনও বস্তুর উপর ReregisterForFinalize বলা হয় যার জন্য SuppressFinalize বলা হয় নি।

এটি একটি জগাখিচুড়ি একটি বিট। আমি ডকুমেন্টেশন ম্যানেজার সঙ্গে এটি নিতে হবে।

গল্পটির নৈতিক, অবশ্যই, যদি আপনি ডকুমেন্টেশনে বর্ণিত নিয়মগুলি লঙ্ঘন করেন তবে এটি তাদের লঙ্ঘন বন্ধ করুন

16
যোগ
যদি আপনি SuppressFinalize কোনও একটি ReRegisterForFinalize এর আগে কল করুন, এটি কেবল একবার বলা হয়। মূলত, ReregisterForFinalize কলগুলির মধ্যে অন্তত 1 <�কোড> দমনকারী অন্তভুক্ত হওয়া আবশ্যক।
যোগ লেখক user7116, উৎস
আরে, masochists এছাড়াও প্রোগ্রামার হয়। সংখ্যালঘুদের উপর পদোন্নতি না, ব্রো।
যোগ লেখক Igby Largeman, উৎস
ধন্যবাদ @ ইरिक, আমি সচেতন ছিলাম যে এই কোডটি লঙ্ঘনের লঙ্ঘন করছে এবং আমি নিশ্চিতভাবেই কোনও সুষম প্রোগ্রামে কোনও উপায়ে কোনও উপায়ে ব্যবহার করতে বলব না।
যোগ লেখক Rich O'Kelly, উৎস

আমি অনুমান করতে পারি ... এবং এটি সত্যিই হল শুধুমাত্র অনুমান। যেমন এরিক বলে, এই ধরনের নিয়ম ভঙ্গ করবেন না :) এই অনুমান শুধুমাত্র নিরপেক্ষ ফটকা এবং আগ্রহের জন্য।

আমি জড়িত দুটি তথ্য কাঠামো আছে সন্দেহ:

  • একটি চূড়ান্তকরণ সারি
  • বস্তুর শিরোনাম

যখন জিসি নোটিশ দেয় যে একটি বস্তু আবর্জনা সংগ্রহের জন্য যোগ্য, আমি সন্দেহ করি এটি বস্তুর শিরোনামটি পরীক্ষা করে এবং চূড়ান্তকরণ সারিতে রেফারেন্স যুক্ত করে। আপনার কোডগুলি SuppressFinalization এ আচরণ প্রতিরোধ করছে।

আলাদাভাবে, চূড়ান্তকরণ থ্রেড চূড়ান্তকরণ সারির মাধ্যমে সঞ্চালিত হয় এবং এটি খুঁজে পায় সবকিছু জন্য চূড়ান্তকারী কল। ReRegisterForFinalize এ আপনার কলগুলি রেফারেন্সটি সারিতে শেষ হয়ে যাওয়ার এবং স্বাভাবিকভাবে যুক্ত করার স্বাভাবিক উপায়ে বাইপাস করছে। সাপ্রেসফিনালাইজেশান লাইন থেকে রেফারেন্সটি সরাতে পারে না - এটি শুধুমাত্র স্বাভাবিক উপায়ে সারির সাথে যুক্ত হওয়া থেকে রেফারেন্সটি বন্ধ করছে।

এর সবই আপনি দেখছেন এমন আচরণ ব্যাখ্যা করবে (এবং যা আমি পুনরুত্পাদন করেছি)। এটিও ব্যাখ্যা করে কেন আমি যখন দমনপ্রণালী কলগুলি মুছে ফেলি তখন আমি তিন বার বলা চূড়ান্তকারীটি দেখছি - কারণ এই ক্ষেত্রে "স্বাভাবিক" পথ চূড়ান্তকরণ সারির রেফারেন্স যোগ করে যেমন.

10
যোগ
ধন্যবাদ @ জোন এবং ডেল্ভ, এই আমি সন্দেহ কি। এটা আমার আগের অনুমিত (এবং প্রকটভাবে ভুল) মানসিক মডেলের বিপরীত, যা একটি পদ্ধতি যোগ করে এবং অন্যটি চূড়ান্তকরণ টেবিলে থেকে সরানো হয়। এটি সম্ভবত দস্তাবেজ ব্যবহারের বিরুদ্ধে, তবে একটি নজরদারী মনে হচ্ছে যে যদি কোনও বস্তু চূড়ান্তকরণের জন্য পুনরায় নিবন্ধিত হয় তবে এটি কখনই দমন করা যাবে না, আমি কারণটি জানতে আগ্রহী ছিলাম - আমি কার্যকরী কারণে অনুমান করি। Mono behaves বেশ আকর্ষণীয় কিভাবে sehe এর তদন্ত, আমি মনে করি যে স্পষ্টভাবে অনির্ধারিত আচরণ সৌন্দর্য!
যোগ লেখক Rich O'Kelly, উৎস
চমৎকার কল, জন। সিএসআই উৎসের দিকে তাকিয়ে যে এমএসএস কিছুক্ষণ আগে মুক্তি পেয়েছে, ReRegisterForFinalize() পদ্ধতিতে একটি যদি বিবৃতি থাকে তবে বলছে "যদি আমি চূড়ান্ত হিসাবে চিহ্নিত হয়েছি, সরান যে চিহ্ন। যদি না, শুধু আমাকে সারিতে যোগ করুন। " সুতরাং আপনি যদি প্রথমবার চাপ না দিয়ে পুনর্নবীকরণকে দুইবার কল করেন, তবে বস্তুটি দুইবার সারিতে যোগ করা হয়। তারপরে, তিনবার বিট সাফ করুন (যা কিছুই করে না, সত্যিই, বিটটি কখন শুরু হতে শুরু করে নি!) যে কোন ক্ষেত্রে, সর্বদা উজ্জ্বল ফটকা, যেমন।
যোগ লেখক dlev, উৎস

আকর্ষণীয় ডেটাপয়েন্টস:

  • mono 2.10.8.1 on linux doesn't call finalizer
  • mono 2.8 on linux doesn't call finalizer: http://ideone.com/J6pl4
  • mono 2.8.1 on Win32 doesn't call finalizer
  • mono 2.6.7 on Win32 doesn't call finalizer

  • .NET 3.5 on Win32 calls finalizer twice

রেফারেন্স জন্য টেস্ট কোড:

class Program
{
    static void Main(string[] args)
    {
       //The MyClass type has a Finalize method defined for it
       //Creating a MyClass places a reference to obj on the finalization table.
        var myClass = new MyClass();

       //Append another 2 references for myClass onto the finalization table.
        System.GC.ReRegisterForFinalize(myClass);
        System.GC.ReRegisterForFinalize(myClass);
       //There are now 3 references to myClass on the finalization table.

        System.GC.SuppressFinalize(myClass);
        System.GC.SuppressFinalize(myClass);
        System.GC.SuppressFinalize(myClass);

       //Remove the reference to the object.
        myClass = null;

       //Force the GC to collect the object.
        System.GC.Collect(2, System.GCCollectionMode.Forced);

       //The first call to obj's Finalize method will be discarded but
       //two calls to Finalize are still performed.
    }
}

class MyClass
{
    ~MyClass()
    {
        System.Console.WriteLine("Finalise() called");
    }
}
5
যোগ

আমি এই 'অনির্দিষ্ট আচরণ' এর রাজত্ব অধীনে আসে সন্দেহ। যদি আপনি ডকুমেন্টেশনটির দিকে নজর রাখেন তবে ReregisterForFinalize </কোড> এবং suppressfinalize , তারা বলে:

obj পরামিতিটি অবশ্যই এই পদ্ধতির আহ্বায়ক হওয়া আবশ্যক।

এবং যে আপনার কোড জন্য ক্ষেত্রে না।

2
যোগ
চমৎকার পিকআপ, যদিও এটি আকর্ষণীয়ভাবে যথেষ্ট। নেটটি যদি কমপক্ষে 1 SuppressFinalize ReRegisterForFinalize কলগুলির মধ্যে ইন্টারলভ না করে।
যোগ লেখক user7116, উৎস