আইডিস্পোজেবল ইন্টারফেসের যথাযথ ব্যবহার


1657

মাইক্রোসফ্ট ডকুমেন্টেশন পড়ে আমি জানি যে IDisposableইন্টারফেসের "প্রাথমিক" ব্যবহারটি নিয়ন্ত্রণহীন সংস্থানগুলি পরিষ্কার করা।

আমার কাছে, "পরিচালনা না করা" এর অর্থ ডাটাবেস সংযোগ, সকেট, উইন্ডো হ্যান্ডেল ইত্যাদির মতো জিনিস তবে আমি কোডটি দেখেছি যেখানে Dispose()পদ্ধতিটি নিখরচায় পরিচালিত সংস্থাগুলিতে প্রয়োগ করা হয় , যা আমার কাছে অপ্রয়োজনীয় বলে মনে হয়, যেহেতু আবর্জনা সংগ্রাহকের যত্ন নেওয়া উচিত এটা তোমার জন্য

উদাহরণ স্বরূপ:

public class MyCollection : IDisposable
{
    private List<String> _theList = new List<String>();
    private Dictionary<String, Point> _theDict = new Dictionary<String, Point>();

    // Die, clear it up! (free unmanaged resources)
    public void Dispose()
    {
        _theList.clear();
        _theDict.clear();
        _theList = null;
        _theDict = null;
    }

আমার প্রশ্ন হ'ল এটি কি আবর্জনা সংগ্রহকারীকে ফ্রি মেমরির ব্যবহার করে MyCollectionযা সাধারণভাবে তার চেয়ে দ্রুততর কোনও দ্রুত ব্যবহার করে ?

সম্পাদনা : এখনও অবধি লোকজনিত ব্যবস্থাপনার সংস্থান এবং বিটম্যাপের মতো নিয়ন্ত্রণহীন সংস্থানগুলি পরিষ্কার করতে আইডিস্পসোবল ব্যবহারের কয়েকটি ভাল উদাহরণ পোস্ট করেছেন। তবে ধরুন যে _theListউপরের কোডটিতে মিলিয়ন স্ট্রিং রয়েছে এবং আপনি আবর্জনা সংগ্রাহকের অপেক্ষা না করে এখনই সেই স্মৃতিটি মুক্ত করতে চেয়েছিলেন । উপরের কোডটি কি তা সম্পাদন করবে?


34
আমি গৃহীত উত্তরটি পছন্দ করি কারণ এটি আপনাকে আইডিসপোজেবল ব্যবহারের সঠিক 'প্যাটার্ন' বলে, তবে ওপি যেমন তার সম্পাদনায় বলেছেন, এটি তার উদ্দেশ্যযুক্ত প্রশ্নের উত্তর দেয় না। আইডিস্পোজেবল জিসিকে 'কল' করে না, এটি কেবল একটি বস্তুকে ধ্বংসযোগ্য হিসাবে চিহ্নিত করে। তবে জিসি ইন কিক করার অপেক্ষা অপেক্ষা 'এখনই' মেমরি মুক্ত করার আসল উপায় কী? আমি মনে করি এই প্রশ্নটি আরও আলোচনার দাবি রাখে।
পুনিত ভোড়া

40
IDisposableকিছুই চিহ্নিত করে না। Disposeপদ্ধতি আছে এটা উদাহরণস্বরূপ দ্বারা ব্যবহৃত সম্পদ পরিষ্কার করতে কি আছে কি। জিসির সাথে এর কোন যোগসূত্র নেই।
জন স্যান্ডার্স

4
@John। আমি বুঝতে পারি IDisposable। এবং এ কারণেই আমি বলেছিলাম যে স্বীকৃত উত্তরটি আইপিআইএসটি <i> মেমরি মুক্ত করার ক্ষেত্রে </ i> সহায়তা করবে কিনা সে সম্পর্কে ওপি'র উদ্দেশ্যযুক্ত প্রশ্নের (এবং ফলো-আপ সম্পাদনা) এর উত্তর দেয় না। যেহেতু IDisposableনিঃশব্দ মেমরির সাথে কেবল কোনও সংস্থান নেই, তবে আপনি যেমনটি বলেছিলেন, পরিচালিত রেফারেন্সগুলি শূন্য করার জন্য কোনও প্রয়োজন নেই যা ওপি তাঁর উদাহরণে যা করছিল তা নয়। সুতরাং, তাঁর প্রশ্নের সঠিক উত্তর হ'ল "না, এটি ফ্রি মেমরির কোনও দ্রুত সাহায্য করে না In বাস্তবে, এটি নিখরচায় স্মৃতিকে মোটেই সহায়তা করে না, কেবলমাত্র উত্স"। তবে যাইহোক, আপনার ইনপুট জন্য ধন্যবাদ।
পুনিত ভোড়া

9
@ ডিজিগেক: যদি এটি হয় তবে আপনার বলা উচিত ছিল না "আইডিস্পোজেবল জিসিকে 'কল' করে না, এটি কেবল একটি বিষয়টিকে ধ্বংসাত্মক হিসাবে চিহ্নিত করে"
জন স্যান্ডার্স

5
@ ডিজিজিক: স্মৃতিচারণকে নির্দ্বিধায় মুক্ত করার কোনও গ্যারান্টিযুক্ত উপায় নেই। আপনি জিসি কলেক্ট () কল করতে পারেন, তবে এটি একটি বিনীত অনুরোধ, দাবি নয়। সমস্ত চলমান থ্রেডগুলি আবর্জনা সংগ্রহের জন্য এগিয়ে যাওয়ার জন্য স্থগিত করতে হবে - আপনি আরও শিখতে চাইলে .NET সেফপয়েন্টগুলির ধারণাটি পড়ুন, উদাহরণস্বরূপ, এমএসডিএন.ইম.সাইক্রোসফট /en-us/library/678ysw69(v=vs.110 )। aspx । যদি কোনও থ্রেড স্থগিত করা না যায়, উদাহরণস্বরূপ, কারণ পরিচালনা না করা কোডে কল রয়েছে, জিসি.কলেক্ট () কিছু করতে পারে না।
কংক্রিট গ্যানেট

উত্তর:


2608

নিষ্পত্তি করার বিষয়টি হ'ল পরিচালনাহীন সংস্থানগুলি মুক্ত করা। এটি কোনও পর্যায়ে করা দরকার, অন্যথায় সেগুলি কখনই পরিষ্কার করা হবে না। আবর্জনা সংগ্রহকারী কোনও প্রকারের পরিবর্তনে কীভাবে কল করতে জানেন তা জানেন না, এটি কল করার দরকার আছে কিনা তা তা জানেন নাDeleteHandle()IntPtrDeleteHandle()

দ্রষ্টব্য : একটি অপরিকল্পিত সংস্থান কী? যদি আপনি এটি মাইক্রোসফ্ট। নেট ফ্রেমওয়ার্কে খুঁজে পান: এটি পরিচালিত। আপনি যদি এমএসডিএন ঘুরে বেড়াতে যান তবে এটি নিয়ন্ত্রণহীন। .NET ফ্রেমওয়ার্কে আপনার জন্য উপলব্ধ সমস্ত কিছুর আরামদায়ক জগতের বাইরে যাওয়ার জন্য আপনি যে কোনও কিছু পি / ইনভোক কলগুলি ব্যবহার করেছেন - এটি নেট ফ্রেমওয়ার্কটি নিয়ন্ত্রণহীন - এবং এটি পরিষ্কার করার জন্য আপনি এখন দায়বদ্ধ।

আপনি যে অবজেক্টটি তৈরি করেছেন তার অপ্রয়োজনীয় সংস্থানগুলি পরিষ্কার করার জন্য বাইরের বিশ্ব কল করতে পারে এমন কিছু পদ্ধতি প্রকাশ করতে হবে। আপনার পছন্দ মত পদ্ধতিটির নাম দেওয়া যেতে পারে:

public void Cleanup()

অথবা

public void Shutdown()

তবে পরিবর্তে এই পদ্ধতির একটি মানক নাম রয়েছে:

public void Dispose()

এমনকি একটি ইন্টারফেসও তৈরি হয়েছিল, IDisposableএটির একটি মাত্র পদ্ধতি রয়েছে:

public interface IDisposable
{
   void Dispose()
}

সুতরাং আপনি আপনার অবজেক্টটি IDisposableইন্টারফেসটি প্রকাশ করে দিয়েছেন এবং সেইভাবে আপনি প্রতিশ্রুতি দিয়েছিলেন যে আপনি আপনার নিয়ন্ত্রণহীন সংস্থানগুলি পরিষ্কার করার জন্য সেই একক পদ্ধতিটি লিখেছেন:

public void Dispose()
{
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
}

এবং তুমি করে ফেলেছ. আপনি আরও ভাল করতে পারেন বাদে।


যদি আপনার অবজেক্টটি 250 এমবি সিস্টেম.ড্রেইং.বিটম্যাপ (অর্থাত্। নেটটি পরিচালিত বিটম্যাপ বর্গ) কিছু ধরণের ফ্রেম বাফার হিসাবে বরাদ্দ করে থাকে ? অবশ্যই, এটি একটি পরিচালিত .NET অবজেক্ট এবং আবর্জনা সংগ্রহকারী এটিকে মুক্ত করবে। তবে আপনি কি সত্যিই 250MB মেমরিটি কেবল সেখানে বসে থাকতে চান - আবর্জনা সংগ্রহকারী অবশেষে আসার জন্য অপেক্ষা করে এবং এটিকে মুক্ত করবেন? যদি একটি ওপেন ডাটাবেস সংযোগ থাকে ? অবশ্যই আমরা এই সংযোগটি উন্মুক্ত বসে থাকতে চাই না, জিসিটি অবজেক্টটি চূড়ান্ত করার অপেক্ষা করছে।

যদি ব্যবহারকারী কল করেছে Dispose()(যার অর্থ তারা আর বস্তুটি ব্যবহারের পরিকল্পনা করে না) তবে কেন এই অপব্যয়কারী বিটম্যাপস এবং ডাটাবেস সংযোগগুলি থেকে মুক্তি পাবেন না?

সুতরাং এখন আমরা করব:

  • নিয়ন্ত্রণহীন সম্পদগুলি থেকে মুক্তি পান (কারণ আমাদের আছে), এবং
  • পরিচালিত সংস্থানগুলি থেকে মুক্তি পান (কারণ আমরা সহায়ক হতে চাই)

সুতরাং আসুন Dispose()এই পরিচালিত অবজেক্টগুলি থেকে মুক্তি পেতে আমাদের পদ্ধতিটি আপডেট করুন :

public void Dispose()
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);

   //Free managed resources too
   if (this.databaseConnection != null)
   {
      this.databaseConnection.Dispose();
      this.databaseConnection = null;
   }
   if (this.frameBufferImage != null)
   {
      this.frameBufferImage.Dispose();
      this.frameBufferImage = null;
   }
}

এবং সব ভাল, আপনি আরও ভাল করতে পারেন বাদে !


যদি ব্যক্তিটি আপনার বস্তুটি বলতে ভুলে যায় তবে কী হবে Dispose()? তারপরে তারা কিছু নিয়ন্ত্রিত সংস্থান ফাঁস করে দিত !

দ্রষ্টব্য: তারা পরিচালিত সংস্থানগুলি ফাঁস করবে না , কারণ অবশেষে আবর্জনা সংগ্রহকারী ব্যাকগ্রাউন্ড থ্রেডে চলতে চলেছে এবং কোনও অব্যবহৃত অবজেক্টের সাথে সম্পর্কিত স্মৃতি মুক্ত করে। এটিতে আপনার অবজেক্ট এবং যে কোনও পরিচালিত অবজেক্ট (যেমন Bitmapএবং এটি DbConnection) অন্তর্ভুক্ত থাকবে।

যদি ব্যক্তি কল করতে ভুলে যায় তবে Dispose()আমরা এখনও তাদের বেকন সংরক্ষণ করতে পারি ! আমাদের এখনও তাদের জন্য এটি কল করার একটি উপায় রয়েছে : অবশেষে আবর্জনা সংগ্রহকারী যখন আমাদের অবজেক্টটি নিখরচায় (অর্থাত্ চূড়ান্ত করা) হয়ে যায়।

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

আবর্জনা সংগ্রাহক দ্বারা আমাদের অবজেক্টের ধ্বংসগুলি সেই সমস্যাযুক্ত অব্যবহৃত সংস্থানগুলি মুক্ত করার উপযুক্ত সময়। আমরা Finalize()পদ্ধতিটি ওভাররাইড করে এটি করি ।

দ্রষ্টব্য: সি # তে, আপনি স্পষ্টভাবে Finalize()পদ্ধতিটিকে ওভাররাইড করবেন না । আপনি একটি পদ্ধতি যা লিখতে মত দেখাচ্ছে একটি সি ++ বিনাশকারী , এবং কম্পাইলার আপনার বাস্তবায়ন হতে যে সময় লাগে Finalize()পদ্ধতি:

~MyObject()
{
    //we're being finalized (i.e. destroyed), call Dispose in case the user forgot to
    Dispose(); //<--Warning: subtle bug! Keep reading!
}

কিন্তু কোডটিতে একটি বাগ আছে। আপনি দেখুন, আবর্জনা সংগ্রাহক একটি পটভূমি থ্রেড চলমান ; আপনি দুটি ক্রমকে ধ্বংস করার আদেশটি জানেন না। এটি সম্পূর্ণরূপে সম্ভব যে আপনার Dispose()কোডে, আপনি যে ব্যবস্থাপনিত অব্যবস্থা থেকে মুক্তি পাওয়ার চেষ্টা করছেন সেটি আর নেই (কারণ আপনি সহায়ক হতে চেয়েছিলেন):

public void Dispose()
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.gdiCursorBitmapStreamFileHandle);

   //Free managed resources too
   if (this.databaseConnection != null)
   {
      this.databaseConnection.Dispose(); //<-- crash, GC already destroyed it
      this.databaseConnection = null;
   }
   if (this.frameBufferImage != null)
   {
      this.frameBufferImage.Dispose(); //<-- crash, GC already destroyed it
      this.frameBufferImage = null;
   }
}

আপনার যা প্রয়োজন তা হ'ল একটি উপায় Finalize()যা বলার অপেক্ষা রাখে না Dispose()যে এটি পরিচালনা করা সংস্থানগুলিতে স্পর্শ না করা উচিত (কারণ তারা সম্ভবত সেখানে থাকবেন না), যদিও এখনও পরিচালনা না করা সংস্থানগুলি মুক্ত করে।

এটি করার জন্য আদর্শ প্যাটার্নটি হল Finalize()এবং Dispose()উভয়ই তৃতীয় (!) পদ্ধতি কল করে ; আপনি যখন কোনও বুলিয়ানকে পাস করে বলছেন যে আপনি যদি এটিকে কল করছেন Dispose()(এর বিপরীতে Finalize()), যার অর্থ এটি বিনামূল্যে পরিচালিত সংস্থানগুলিতে নিরাপদ।

এই অভ্যন্তরীণ পদ্ধতিতে "কোরডিসপস", বা "মাই আইটার্নাল ডিসপস" এর মতো কিছু স্বেচ্ছাসেবী নাম দেওয়া যেতে পারে তবে এটি এটিকে ডাকার traditionতিহ্য Dispose(Boolean):

protected void Dispose(Boolean disposing)

তবে আরও সহায়ক প্যারামিটারের নাম হতে পারে:

protected void Dispose(Boolean itIsSafeToAlsoFreeManagedObjects)
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);

   //Free managed resources too, but only if I'm being called from Dispose
   //(If I'm being called from Finalize then the objects might not exist
   //anymore
   if (itIsSafeToAlsoFreeManagedObjects)  
   {    
      if (this.databaseConnection != null)
      {
         this.databaseConnection.Dispose();
         this.databaseConnection = null;
      }
      if (this.frameBufferImage != null)
      {
         this.frameBufferImage.Dispose();
         this.frameBufferImage = null;
      }
   }
}

এবং আপনি এই IDisposable.Dispose()পদ্ধতির প্রয়োগটি এতে পরিবর্তন করুন :

public void Dispose()
{
   Dispose(true); //I am calling you from Dispose, it's safe
}

এবং আপনার চূড়ান্তকরণকারী:

~MyObject()
{
   Dispose(false); //I am *not* calling you from Dispose, it's *not* safe
}

দ্রষ্টব্য : যদি আপনার অবজেক্ট প্রয়োগ করে এমন কোনও বস্তু থেকে অবতরণ করে Dispose, তবে আপনি ডিসপোজকে ওভাররাইড করার সময় তাদের বেস ডিসপোজ পদ্ধতিটি কল করতে ভুলবেন না :

public override void Dispose()
{
    try
    {
        Dispose(true); //true: safe to free managed resources
    }
    finally
    {
        base.Dispose();
    }
}

এবং সব ভাল, আপনি আরও ভাল করতে পারেন বাদে !


যদি ব্যবহারকারী Dispose()আপনার অবজেক্টে কল করে, তবে সবকিছু পরিষ্কার হয়ে গেছে। পরে, আবর্জনা সংগ্রাহক যখন এসে ফিনালাইজ কল করবেন তখন এটি Disposeআবার কল করবে ।

কেবল এটি অপব্যয়কারীই নয়, তবে আপনি যদি ইতিমধ্যে শেষ কলটি থেকে নিষ্পত্তি করেছেন এমন বস্তুর সাথে যদি আপনার অবজেক্টের জাঙ্ক রেফারেন্স থাকে তবে Dispose()আপনি সেগুলি আবার নিষ্পত্তি করার চেষ্টা করবেন!

আপনি আমার কোডে লক্ষ্য করবেন যে আমি যে জিনিসগুলিকে নিষ্পত্তি করেছি তার রেফারেন্সগুলি সরিয়ে দিতে আমি সাবধান ছিলাম, তাই আমি Disposeকোনও জাঙ্ক অবজেক্ট রেফারেন্সের জন্য কল করার চেষ্টা করি না । তবে এটি কোনও সূক্ষ্ম বাগটি প্রবেশ করতে বাধা দেয় নি।

যখন ব্যবহারকারী কল করে Dispose(): হ্যান্ডেলটি কার্সারফিটবিটম্যাপ আইকনসোর্সহ্যান্ডলটি ধ্বংস হয়ে গেছে। পরে যখন আবর্জনা সংগ্রহকারী চালাবেন, এটি আবার একই হ্যান্ডেলটি ধ্বংস করার চেষ্টা করবে।

protected void Dispose(Boolean iAmBeingCalledFromDisposeAndNotFinalize)
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle); //<--double destroy 
   ...
}

আপনি যেভাবে এটি ঠিক করেছেন তা আবর্জনা সংগ্রাহককে বলুন যে এটি অবজেক্টটিকে চূড়ান্ত করার ঝামেলা করার দরকার নেই - এর সংস্থানগুলি ইতিমধ্যে পরিষ্কার হয়ে গেছে, আর কোনও কাজ করার দরকার নেই। আপনি পদ্ধতিতে কল GC.SuppressFinalize()করে এটি করেন Dispose():

public void Dispose()
{
   Dispose(true); //I am calling you from Dispose, it's safe
   GC.SuppressFinalize(this); //Hey, GC: don't bother calling finalize later
}

ব্যবহারকারী যখন ফোন করেছেন Dispose(), আমাদের রয়েছে:

  • নিরবচ্ছিন্ন সম্পদ মুক্ত করেছেন
  • পরিচালিত সংস্থানসমূহ মুক্তি

চূড়ান্তকরণকারীর পরিচালনায় জিসির কোনও অর্থ নেই - সবকিছুর যত্ন নেওয়া হয়েছে।

অব্যবহৃত পরিচালিত সংস্থানগুলি পরিষ্কার করতে আমি ফাইনালাইজ ব্যবহার করতে পারি না?

এর জন্য ডকুমেন্টেশন Object.Finalizeবলেছেন:

ফাইনালাইজ পদ্ধতিটি অবজেক্টটি বিনষ্ট হওয়ার আগে বর্তমান অবজেক্টের দ্বারা পরিচালিত অপরিশোধিত সম্পদগুলিতে ক্লিনআপ ক্রিয়াকলাপ করতে ব্যবহৃত হয়।

তবে এমএসডিএন ডকুমেন্টেশন আরও বলেছে IDisposable.Dispose:

নিরবচ্ছিন্ন রিসোর্সগুলি মুক্ত, মুক্তি, বা পুনরায় সেট করার সাথে যুক্ত অ্যাপ্লিকেশন-সংজ্ঞায়িত কার্য সম্পাদন করে।

তাহলে এটি কোনটি? নিয়ন্ত্রণহীন সংস্থানগুলি পরিষ্কার করার জন্য আমার কোনটি জায়গা? উত্তরটা হচ্ছে:

এটা তোমার পছন্দ! তবে বেছে নিন Dispose

আপনি অবশ্যই আপনার চিকিত্সাবিহীন ক্লিনআপ ফাইনালাইজারে রাখতে পারবেন:

~MyObject()
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);

   //A C# destructor automatically calls the destructor of its base class.
}

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

ফাইনালাইজার কার্যকর করার সময় সঠিক সময়টি সংজ্ঞায়িত হয়। আপনার শ্রেণীর উদাহরণগুলির জন্য সংস্থানসমূহের নিরঙ্কুশ মুক্তির বিষয়টি নিশ্চিত করতে, একটি ক্লোজ পদ্ধতি প্রয়োগ করুন বা একটি IDisposable.Disposeবাস্তবায়ন সরবরাহ করুন।

Disposeঅপরিকল্পিত সংস্থানগুলি সাফ করার জন্য এটি ব্যবহার করার গুণ ; যখন নিয়ন্ত্রণহীন সংস্থানগুলি পরিষ্কার করা হয় তখন আপনি জানতে ও নিয়ন্ত্রণ করতে পারেন। তাদের ধ্বংস হ'ল "সংজ্ঞাবাদী"


আপনার মূল প্রশ্নের উত্তর দেওয়ার জন্য: জিসি কখন এটি করার সিদ্ধান্ত নেওয়ার পরিবর্তে এখনই মেমরি ছেড়ে দিচ্ছেন না? আমি মুখের স্বীকৃতি সফ্টওয়্যার যা আছে চাহিদা অভ্যন্তরীণ ইমেজ 530 মেগাবাইট পরিত্রাণ পেতে এখন যেহেতু তারা আর প্রয়োজন করছি। যখন আমরা না করি: মেশিনটি একটি অদলবদল থামে ind

বোনাস রিডিং

যে কেউ এই উত্তরের শৈলী পছন্দ করেন (তার কারণ ব্যাখ্যা করার ফলে, কীভাবে প্রকট হয়ে উঠবে), আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি ডন বক্সের প্রয়োজনীয় COM এর প্রথম অধ্যায়টি পড়বেন:

35 পৃষ্ঠায় তিনি বাইনারি অবজেক্ট ব্যবহার করার সমস্যাগুলি ব্যাখ্যা করেছেন এবং আপনার চোখের সামনে সিওএম আবিষ্কার করেছেন। আপনি যখন COM এর কারণ বুঝতে পারবেন , তখন বাকি 300 পৃষ্ঠাগুলি সুস্পষ্ট এবং মাইক্রোসফ্টের বাস্তবায়নের বিশদটি রয়েছে।

আমি মনে করি যে প্রতিটি প্রোগ্রামার যিনি কখনও অবজেক্টস বা সিওএম নিয়ে কাজ করেছেন তাদের খুব কমপক্ষে প্রথম অধ্যায়টি পড়া উচিত। এটি যে কোনও কিছুর সেরা ব্যাখ্যা।

অতিরিক্ত বোনাস পড়া

যখন আপনি জানেন সমস্ত কিছু যখন এরিক লিপার্ট ভুল করে

সুতরাং সঠিক চূড়ান্তকরণকারীটি লেখা সত্যিই খুব কঠিন এবং আমি আপনাকে যে সেরা পরামর্শ দিতে পারি তা হল চেষ্টা না করা


12
আপনি আরও ভাল করতে পারেন - ডিসপোজ করতে আপনাকে GC.SuppressFinalize () এ কল করতে হবে।
প্লিথ

55
@ ড্যানিয়েল এয়ারউইকার: এটি সত্য। মাইক্রোসফ্ট আপনার জন্য উইন 32 পুরোপুরি বন্ধ করা এবং চমৎকার বিমূর্ত, পোর্টেবল, ডিভাইস স্বাধীন। নেট ফ্রেমওয়ার্ক কলগুলিতে আটকে থাকতে পছন্দ করবে। আপনি নীচে অপারেটিং সিস্টেমের চারপাশে poking যেতে চান; কারণ আপনি ভাবেন যে আপনি জানেন ওএস কী চলছে: আপনি নিজের জীবন নিজের হাতে নিচ্ছেন। প্রত্যেকটি .NET অ্যাপ উইন্ডোজে বা কোনও ডেস্কটপে চলছে না।
ইয়ান বয়ড

34
এটি একটি দুর্দান্ত উত্তর তবে আমি মনে করি এটি কোনও স্ট্যান্ডার্ড কেস এবং এমন একটি ক্ষেত্রে যেখানে ক্লাসটি বেসক্লাস থেকে ইতিমধ্যে নিষ্পত্তি কার্যকর করেছে তার ক্ষেত্রে একটি চূড়ান্ত কোড তালিকা থেকে উপকৃত হবে। যেমন এখানে পড়ার পরে ( এমএসডিএন.মাইক্রোসফটকম /en-us/library/aa720161%28v=vs.71%29.aspx ) পাশাপাশি ইতিমধ্যে ডিসপোজ প্রয়োগকারী ক্লাস থেকে প্রাপ্ত যখন আমি কী করব সে সম্পর্কে আমি বিভ্রান্ত হয়ে পড়েছি ( আরে আমি এই নতুন)।
ইন্টিগ্রে 753

5
@ গ্রেগস এবং অন্যান্য: সাধারণত আমি রেফারেন্স সেট করতে বিরক্ত করব না null। প্রথমত, এর অর্থ হল আপনি এগুলি তৈরি করতে পারবেন না readonlyএবং দ্বিতীয়ত, আপনাকে খুব কুরুচিপূর্ণ !=nullচেক করতে হবে (উদাহরণ কোডের মতো)। আপনার একটি পতাকা থাকতে পারে disposedতবে এটি নিয়ে মাথা ঘামানো না সহজ। .NET GC যথেষ্ট আক্রমনাত্মক যে কোনও ক্ষেত্রের রেফারেন্সটি লাইনটি xপেরিয়ে যাওয়ার পরে আর ব্যবহার করা হবে না x.Dispose()
22:58

7
আপনার উল্লিখিত ডন বক্সের বইয়ের দ্বিতীয় পৃষ্ঠায় তিনি অনুসন্ধান অ্যালগরিদমের একটি ও (1) প্রয়োগের উদাহরণ ব্যবহার করেছেন, যার "বিবরণ পাঠকের জন্য অনুশীলন হিসাবে রেখে গেছে"। আমি হেসেছিলাম.
5313

65

IDisposableusingবিবৃতিটি কাজে লাগাতে এবং পরিচালিত অবজেক্টগুলির নির্বিচারে ক্লিনআপ করার সহজ পদ্ধতির সুবিধা নিতে প্রায়শই ব্যবহৃত হয় ।

public class LoggingContext : IDisposable {
    public Finicky(string name) {
        Log.Write("Entering Log Context {0}", name);
        Log.Indent();
    }
    public void Dispose() {
        Log.Outdent();
    }

    public static void Main() {
        Log.Write("Some initial stuff.");
        try {
            using(new LoggingContext()) {
                Log.Write("Some stuff inside the context.");
                throw new Exception();
            }
        } catch {
            Log.Write("Man, that was a heavy exception caught from inside a child logging context!");
        } finally {
            Log.Write("Some final stuff.");
        }
    }
}

6
আমি ব্যক্তিগতভাবে এটি পছন্দ করি তবে এটি ফ্রেমওয়ার্ক ডিজাইনের নির্দেশিকাগুলির সাথে সত্যই মাতামাতি করে না।
এমকিপিপি

4
আমি এটিকে যথাযথ নকশা হিসাবে বিবেচনা করব কারণ এটি সহজেই নির্জনবাদী স্কোপগুলি এবং স্কোপ নির্মাণগুলি / ক্লিনআপগুলিকে সক্ষম করে, বিশেষত যখন ব্যতিক্রমী-হ্যান্ডলিং, লকিং এবং জটিল পদ্ধতিতে অবরুদ্ধ-রিসোর্স ব্যবহার করে ব্লকগুলিতে সংযুক্ত থাকে। ভাষা এটি প্রথম শ্রেণির বৈশিষ্ট্য হিসাবে উপলব্ধ করে।
yfeldblum

এটি ঠিক এফডিজিতে উল্লিখিত বিধিগুলি অনুসরণ করে না তবে এটি "স্টেটমেন্ট ব্যবহার করে" ব্যবহার করার জন্য এটি অবশ্যই নিদর্শনটির একটি বৈধ ব্যবহার।
স্কট ডরম্যান

2
যতক্ষণ না লগ.আউটডেন্ট নিক্ষেপ করে না ততক্ষণ এগুলিতে অবশ্যই কোনও ভুল নেই।
ড্যানিয়েল আরউইকার

1
নানা উত্তর এটা ব্যতিক্রম নিরাপত্তার জন্য "বিশ্লেষণ করা আচরণ" পাওয়ার জন্য একটি উপায় হিসেবে IDisposable এবং "ব্যবহার" ব্যবহার করতে অবমাননাকর? কেন বিভিন্ন লোক এই কৌশলটি পছন্দ / অপছন্দ করে সে সম্পর্কে কিছুটা বিশদে যান। এটি কিছুটা বিতর্কিত।
ব্রায়ান

44

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

ডিসপোজ প্যাটার্নটি কীভাবে বাস্তবায়ন করা যায় সে সম্পর্কে আরও বিশদ জানতে আপনি এই নিবন্ধটি একবার দেখে নিতে পারেন তবে এটি মূলত: এর মতো দেখায়:

public class SimpleCleanup : IDisposable
{
    // some fields that require cleanup
    private SafeHandle handle;
    private bool disposed = false; // to detect redundant calls

    public SimpleCleanup()
    {
        this.handle = /*...*/;
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.
                if (handle != null)
                {
                    handle.Dispose();
                }
            }

            // Dispose unmanaged managed resources.

            disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

এখানে যে পদ্ধতিটি সবচেয়ে গুরুত্বপূর্ণ তা হ'ল ডিসপোজ (বুল), যা আসলে দুটি ভিন্ন পরিস্থিতিতে পরিচালিত হয়:

  • নিষ্পত্তি == সত্য: ব্যবহারকারীর কোড দ্বারা পদ্ধতিটি প্রত্যক্ষ বা অপ্রত্যক্ষভাবে ডেকে আনা হয়েছে। পরিচালিত এবং অপরিকল্পিত সংস্থানগুলি নিষ্পত্তি করা যেতে পারে।
  • নিষ্পত্তি == মিথ্যা: পদ্ধতিটি চূড়ান্তকরণকারীর অভ্যন্তর থেকে রানটাইম দ্বারা ডেকে আনা হয়েছে, এবং আপনার অন্যান্য বিষয়গুলি উল্লেখ করা উচিত নয়। কেবল অপরিকল্পিত সম্পদ নিষ্পত্তি করা যেতে পারে।

জিসিকে ক্লিনআপটি কেবল যত্ন নেওয়ার সুযোগ দেওয়ার সাথে সমস্যাটি হ'ল জিসি কখন একটি সংগ্রহ চক্র চালাবেন তার উপর আপনার কোনও নিয়ন্ত্রণ নেই (আপনি জিসি.কলেক্ট্রে কল করতে পারেন), তবে আপনার সত্যিকারের উচিত নয়) যাতে সংস্থানগুলি থাকতে পারে প্রয়োজনের চেয়ে প্রায় দীর্ঘ মনে রাখবেন, ডিসপোজ () কল করার ফলে আসলে কোনও সংগ্রহ চক্র হয় না বা কোনও উপায়ে জিসিকে অবজেক্টটি সংগ্রহ / মুক্ত করতে পারে না; এটি কেবলমাত্র ব্যবহৃত সংস্থানগুলিকে আরও নির্বিচারে পরিষ্কার করার উপায় সরবরাহ করে এবং জিসিকে জানান যে এই ক্লিনআপটি ইতিমধ্যে সম্পন্ন হয়েছে।

আইডিস্পোজেবলের পুরো পয়েন্ট এবং নিষ্পত্তি করার প্যাটার্নটি তাত্ক্ষণিকভাবে মেমরি মুক্ত করার বিষয়ে নয়। ডিসপোজ করার কেবলমাত্র একবারে কলটি আসলে তাত্ক্ষণিকভাবে মেমরি মুক্ত করার সুযোগ পাবে যখন এটি নিষ্পত্তি == মিথ্যা পরিস্থিতি পরিচালনা করছে এবং অপ্রয়োজনীয় সংস্থানগুলি পরিচালনা করছে। পরিচালিত কোডের জন্য, জিসি সংগ্রহ চক্র না চালানো পর্যন্ত মেমরিটি আসলে পুনরুদ্ধার করা হবে না, যার সত্যিকার অর্থে আপনার কোনও নিয়ন্ত্রণ নেই (জিসি.কালেক্টকে কল করা) (যা আমি ইতিমধ্যে উল্লেখ করেছি ভাল ধারণা নয়)।

আপনার পরিস্থিতি সত্যই বৈধ নয় .NET- এ স্ট্রিংগুলি কোনও নিরবচ্ছিন্ন সংস্থান ব্যবহার করে না এবং আইডিজিপোজেবল প্রয়োগ করে না, তাদের "পরিষ্কার" করতে বাধ্য করার কোনও উপায় নেই।


4
আপনি চূড়ান্তকরণ বাস্তবায়ন করতে ভুলবেন না?
বুদা

@ বুদ্দা: না, সে সেফহ্যান্ডল ব্যবহার করছে। বিনষ্টকারীর দরকার নেই।
হেন্ক হলটারম্যান

9
ডিসপোজ () এ একাধিক কলের জন্য সুরক্ষা নেট যুক্ত করার জন্য +1। অনুমানটি বলছে একাধিক কল নিরাপদ হওয়া উচিত। মাইক্রোসফ্টের অনেকগুলি ক্লাস এটিকে বাস্তবায়িত করতে ব্যর্থ হয় এবং আপনি বিরক্তিকর অবজেক্টডিসপোজড এক্সপ্লেশন পেয়ে যান।
জেসি চিশলম

5
তবে ডিসপোজ (বুল নিষ্পত্তি) হ'ল আপনার সিম্পলক্লিনআপ ক্লাসে আপনার নিজস্ব পদ্ধতি এবং ফ্রেমওয়ার্কের মাধ্যমে কখনই ডাকা হবে না। যেহেতু আপনি এটিকে কেবল পরামিতি হিসাবে "সত্য" দিয়ে কল করেছেন তাই 'নিষ্পত্তি' কখনই মিথ্যা হবে না। আপনার কোডটি আইডিএসপোজেবলের জন্য এমএসডিএন উদাহরণের সাথে খুব সমান, তবে @ বুদ্দা উল্লেখ করেছেন যে চূড়ান্তকরণকারীর অভাব রয়েছে, যেখানে অপসারণের সাথে = মিথ্যা কল আসবে।
yoyo

19

ডিসপোজ ডাকার পরে কোনও অবজেক্টের পদ্ধতিতে আর কল করা উচিত নয় (যদিও কোনও বস্তুর ডিসপোজ করার জন্য আরও কলগুলি সহ্য করা উচিত)। সুতরাং প্রশ্নের উদাহরণটি নির্বোধ। যদি ডিসপোজ বলা হয়, তবে অবজেক্টটি নিজেই ফেলে দেওয়া যেতে পারে। সুতরাং ব্যবহারকারীর কেবলমাত্র সেই পুরো অবজেক্টের সমস্ত রেফারেন্স বাতিল করতে হবে (এগুলি নালায় সেট করুন) এবং এর সাথে সম্পর্কিত অভ্যন্তরীণ সমস্ত জিনিস স্বয়ংক্রিয়ভাবে পরিষ্কার হয়ে যাবে।

পরিচালিত / নিয়ন্ত্রণহীন এবং অন্যান্য উত্তরের আলোচনার বিষয়ে সাধারণ প্রশ্ন হিসাবে, আমি মনে করি যে এই প্রশ্নের কোনও উত্তর একটি অপরিকল্পিত সংস্থার সংজ্ঞা দিয়ে শুরু করতে হবে।

এটি কীভাবে ফুটে ওঠে তা হ'ল একটি ফাংশন রয়েছে যা আপনি সিস্টেমকে একটি স্টেটে রাখার জন্য কল করতে পারেন এবং সেখানে আরও একটি ফাংশন রয়েছে যা আপনি এটিকে সেই অবস্থা থেকে ফিরিয়ে আনতে কল করতে পারেন। এখন, আদর্শ উদাহরণ, প্রথম এক একটি ফাংশন যা রিটার্ন একটি ফাইল হ্যান্ডেল, এবং দ্বিতীয় এক একটি কল হতে পারে হতে পারে CloseHandle

তবে - এবং এটিই মূল - এটি কোনও ফাংশনগুলির সাথে মিলে যাওয়া জোড়া হতে পারে। একজন একটি রাষ্ট্র গঠন করে, অন্যটি তা ভেঙে দেয়। যদি রাজ্যটি নির্মিত হয় তবে এখনও ছিন্ন না হয়, তবে উত্সটির একটি উদাহরণ উপস্থিত রয়েছে। টিয়ারডাউনটি সঠিক সময়ে হওয়ার জন্য আপনাকে ব্যবস্থা করতে হবে - সিএলআর দ্বারা সংস্থানটি পরিচালিত হয় না। কেবলমাত্র স্বয়ংক্রিয়ভাবে পরিচালিত সংস্থার ধরণটি মেমরি। এখানে দুটি ধরণের রয়েছে: জিসি এবং স্ট্যাক। মান প্রকারগুলি স্ট্যাক (বা রেফারেন্সের ধরণের অভ্যন্তরে যাত্রায় চলাচল করে) দ্বারা পরিচালিত হয়, এবং রেফারেন্সের প্রকারগুলি জিসি দ্বারা পরিচালিত হয়।

এই ফাংশনগুলির ফলে রাষ্ট্র পরিবর্তন হতে পারে যা অবাধে আন্তঃবাহিত হতে পারে, বা পুরোপুরি নেস্ট করা দরকার to রাষ্ট্র পরিবর্তনগুলি থ্রেডসেফ হতে পারে, বা তারা নাও পারে।

জাস্টিসের প্রশ্নের উদাহরণটি দেখুন। লগ ফাইলের ইনডেন্টেশনের পরিবর্তনগুলি অবশ্যই নিখুঁতভাবে নেস্ট করা উচিত, বা এটি সমস্ত ভুল হয়ে যায়। এছাড়াও তারা থ্রেডসেফ হওয়ার সম্ভাবনা কম।

আপনার অপরিশোধিত সম্পদ পরিষ্কার করার জন্য আবর্জনা সংগ্রাহকের সাথে যাত্রায় চলাচল করা সম্ভব। তবে কেবলমাত্র যদি রাষ্ট্র পরিবর্তনগুলি কার্যক্রমে থ্রেডসেফ হয় এবং দুটি রাজ্যের লাইফটাইম থাকতে পারে যা কোনও উপায়ে ওভারল্যাপ হয়। সুতরাং ন্যায়বিচারের উত্স একটি উদাহরণ অবশ্যই একটি চূড়ান্ত না! এটি কেবল কাউকেই সহায়তা করবে না।

এই ধরণের সংস্থানগুলির জন্য, আপনি কেবল বাস্তবায়ন করতে পারেন IDisposable চূড়ান্তকরণকারী ছাড়াই । চূড়ান্তকরণটি একেবারে alচ্ছিক - এটি হতে হবে। এটি অনেক গ্রন্থে উল্লিখিত বা না উল্লেখ করা হয়েছে।

তারপরে আপনাকে যে usingবিবৃতিটি বলা হয়েছে তা নিশ্চিত করার কোনও সুযোগ পেতে বিবৃতিটি ব্যবহার করতে হবে Dispose। এটি মূলত স্ট্যাকের সাথে যাত্রায় চলাচলের মতো (যাতে চূড়ান্তকরণটি জিসির কাছে হয়,using স্ট্যাকের সাথে হয়)।

অনুপস্থিত অংশটি হ'ল আপনাকে ম্যানুয়ালি ডিসপোজ লিখতে হবে এবং এটি আপনার ক্ষেত্র এবং আপনার বেস শ্রেণিতে কল করতে হবে। সি ++ / সিএলআই প্রোগ্রামারদের এটি করার দরকার নেই। সংকলকটি বেশিরভাগ ক্ষেত্রে এটি তাদের জন্য লেখেন।

একটি বিকল্প আছে, যা আমি রাজ্যগুলিকে পছন্দ করি যে নীড়গুলি পুরোপুরি এবং থ্রেডসেফ নয় (অন্য কিছু বাদে, আইডিস্পোজেবল এড়িয়ে যাওয়া আপনাকে এমন কোনও ব্যক্তির সাথে যুক্তির সমস্যা থেকে বাঁচায় যে প্রতি বর্গের জন্য চূড়ান্তর সংযোজন প্রতিরোধ করতে পারে না যা প্রতিবন্ধী কার্যকর করে) ।

ক্লাস লেখার পরিবর্তে আপনি একটি ফাংশন লিখুন। ফাংশনটি একটি প্রতিনিধিকে আবার কল করতে গ্রহণ করে:

public static void Indented(this Log log, Action action)
{
    log.Indent();
    try
    {
        action();
    }
    finally
    {
        log.Outdent();
    }
}

এবং তারপরে একটি সাধারণ উদাহরণটি হ'ল:

Log.Write("Message at the top");
Log.Indented(() =>
{
    Log.Write("And this is indented");

    Log.Indented(() =>
    {
        Log.Write("This is even more indented");
    });
});
Log.Write("Back at the outermost level again");

প্রবেশ করা ল্যাম্বদা কোড ব্লক হিসাবে কাজ করে, সুতরাং এটি একই উদ্দেশ্যে আপনি নিজের নিয়ন্ত্রণ কাঠামোটি তৈরি করার মতো using , কেবলমাত্র যে আহ্বানকারীকে আপনি এটি ব্যবহার করছেন তার কোনও বিপদ নেই except তারা সংস্থানটি পরিষ্কার করতে ব্যর্থ হতে পারে এমন কোনও উপায় নেই।

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


পুনরায়: "নিষ্পত্তি করার পরে কোনও অবজেক্টের পদ্ধতিতে আর কল করার দরকার নেই"। "উচিত" অপারেটিভ শব্দ হচ্ছে। আপনার যদি অ্যাসিক্রোনাস অ্যাকশনগুলি মুলতুবি থাকে, তবে আপনার বস্তু নিষ্পত্তি হওয়ার পরে এগুলি আসতে পারে। একটি অবজেক্টডিস্পোজড এক্সসেপশন এর কারণ।
জেসি চিশম

আপনারা আমার ব্যতীত একমাত্র উত্তর বলে মনে করছেন যা পরিচালনা না করা সংস্থাগুলিকে এমন অবস্থা জবাব দেয় যা জিসি বুঝতে পারে না idea তবে নিয়ন্ত্রণহীন সংস্থার একটি মূল বিষয় হ'ল যে এক বা একাধিক সত্তা যাদের রাষ্ট্রকে তার রাজ্য পরিষ্কার করার দরকার হতে পারে, সেই সংস্থার যদি "সম্পত্তির মালিকানাধীন" অবজেক্টটি না থাকে তবেও তা বিদ্যমান থাকতে পারে। আপনি আমার সংজ্ঞাটি পছন্দ করেন? খুব অনুরূপ, তবে আমি মনে করি এটি "রিসোর্স" কে আরও কিছু বিশেষ্য-ইশ করে তোলে (যখন এর পরিষেবাগুলির আর প্রয়োজন নেই তখন বিজ্ঞপ্তির বিনিময়ে এটি বাইরের অবজেক্টের "চুক্তি")
সুপারক্যাট

@ সুপের্যাট - আপনি যদি আগ্রহী হন আমি উপরের উত্তরটি লেখার কয়েকদিন পরেই নিম্নলিখিত পোস্টটি লিখেছিলাম: স্মেল্লেগ্যান্টকোড.ওয়ার্ডপ্রেস.com
ড্যানিয়েল আর্উইকার

1
@ ড্যানিয়েলআরউইকার: আকর্ষণীয় নিবন্ধ, যদিও আমি কমপক্ষে এক প্রকারের অপরিশোধিত সম্পদ সম্পর্কে ভাবতে পারি যা আপনি সত্যই আবদ্ধ করেন না: দীর্ঘকালীন অবজেক্টের ইভেন্টগুলির সদস্যতা। ইভেন্টের সাবস্ক্রিপশনগুলি ছদ্মবেশজনক, তবে মেমোরিগুলি অপসারণে সীমাহীন ব্যর্থতাও ব্যয়বহুল হতে পারে। উদাহরণস্বরূপ, একটি সংকলনের জন্য একটি গণক যা গণনার সময় সংশোধন করার অনুমতি দেয় সেটিকে সংগ্রহ থেকে বিজ্ঞপ্তিগুলি আপডেট করার জন্য সাবস্ক্রাইব করতে হবে এবং সংগ্রহটি তার জীবদ্দশায় বহুবার আপডেট হতে পারে। যদি গণনাকারীদের সদস্যতা ছাড়াই ছেড়ে দেওয়া হয় ...
সুপারক্যাট ২ '

1
অপারেশনের জুড়ি enterএবং exitআমি কীভাবে একটি সংস্থান সম্পর্কে চিন্তা করি তার মূল বিষয়। ইভেন্টগুলিতে সাবস্ক্রাইব / সাবস্ক্রাইব করা কোনও অসুবিধা ছাড়াই এতে মাপসই করা উচিত। অরথোগোনাল / ছত্রাকজনিত বৈশিষ্ট্যগুলির ক্ষেত্রে এটি একটি স্মৃতি ফাঁস থেকে কার্যত পৃথক নয়। (এটি আশ্চর্যজনক যেহেতু সাবস্ক্রিপশন কেবল একটি তালিকায় অবজেক্ট যুক্ত করছে))
ড্যানিয়েল আর্উইকার ২ '

17

দৃশ্যগুলি আমি আইডিপসোজেবলের ব্যবহার করি: পরিচালনা না করা সম্পদগুলি পরিষ্কার করুন, ইভেন্টগুলির জন্য সদস্যতা ছাড়ুন, সংযোগ বন্ধ করুন

আইডিসপোজেবল ( থ্রেডসেফ নয় ) বাস্তবায়নের জন্য আমি যে আইডিয়ামটি ব্যবহার করি :

class MyClass : IDisposable {
    // ...

    #region IDisposable Members and Helpers
    private bool disposed = false;

    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing) {
        if (!this.disposed) {
            if (disposing) {
                // cleanup code goes here
            }
            disposed = true;
        }
    }

    ~MyClass() {
        Dispose(false);
    }
    #endregion
}

ফুল প্যাটার্ন ব্যাখ্যা পাওয়া যাবে msdn.microsoft.com/en-us/library/b1yfkh5e.aspx
LicenseQ

3
আপনার নিয়ন্ত্রণহীন সংস্থান না থাকলে কখনও চূড়ান্তকরণকারী অন্তর্ভুক্ত করা উচিত নয়। তারপরেও, পছন্দসই বাস্তবায়নটি সেফহ্যান্ডলে পরিচালনা না করা সংস্থানটি মোড়ানো w
ডেভ ব্ল্যাক

11

হ্যাঁ, এই কোডটি সম্পূর্ণ অপ্রয়োজনীয় এবং অপ্রয়োজনীয় এবং এটি আবর্জনা সংগ্রহকারীকে এমন কিছু করতে দেয় না যা অন্যথায় না করে (মাই কালেকশনের একটি উদাহরণ একবার সুযোগের বাইরে চলে যায়, এটি। বিশেষত .Clear()কলগুলি।

আপনার সম্পাদনার উত্তর: বাছাই করুন। আমি যদি এটি করি:

public void WasteMemory()
{
    var instance = new MyCollection(); // this one has no Dispose() method
    instance.FillItWithAMillionStrings();
}

// 1 million strings are in memory, but marked for reclamation by the GC

স্মৃতি পরিচালনার উদ্দেশ্যে এটি কার্যত এটির মতো:

public void WasteMemory()
{
    var instance = new MyCollection(); // this one has your Dispose()
    instance.FillItWithAMillionStrings();
    instance.Dispose();
}

// 1 million strings are in memory, but marked for reclamation by the GC

আপনার যদি সত্যই সত্যই এই খুব তাত্ক্ষণিকভাবে স্মৃতি মুক্ত করতে হবে, কল করুন GC.Collect()। যদিও এখানে এটি করার কোনও কারণ নেই। স্মৃতি যখন প্রয়োজন হবে তখন তা মুক্ত হবে।


2
পুনরায়: "স্মৃতি যখন প্রয়োজন হবে তখন তা মুক্ত হবে।" বরং বলুন, "যখন জিসি সিদ্ধান্ত নেয় যে এটি প্রয়োজন" " জিসি সিদ্ধান্ত নিতে পারে যে মেমরিটি আসলেই দরকার needed এখনই এটি মুক্ত করা প্রয়োজনীয় নাও হতে পারে তবে কার্যকর হতে পারে।
জেসি চিশলম

1
কিছু কর্নারের কেস রয়েছে যেগুলিতে সংগ্রহের মধ্যে উল্লেখগুলি বাতিল করে দেয় যার ফলে উল্লেখ করা আইটেমগুলির আবর্জনা সংগ্রহ দ্রুত করতে পারে। উদাহরণস্বরূপ, যদি একটি বৃহত অ্যারে তৈরি করা হয় এবং ছোট নতুন তৈরি হওয়া আইটেমের রেফারেন্সগুলি পূর্ণ হয় তবে এর পরে খুব বেশি সময়ের প্রয়োজন হয় না, অ্যারেটি ছেড়ে দেওয়ার ফলে এই আইটেমগুলি পরবর্তী স্তরের 2 জিসি অবধি রাখা হতে পারে, প্রথমে শূন্য করার সময় আইটেমগুলি পরবর্তী স্তর 0 বা স্তর 1 জিসির জন্য যোগ্য করে তুলতে পারে। নিশ্চিত হওয়া দরকার যে লার্জ অবজেক্ট হিপ-তে বড় স্বল্প-জীবিত অবজেক্ট থাকা যাইহোক
আইকি আটকানো

1
... এই জাতীয় অ্যারেগুলি ত্যাগ করার আগে তাদের শূন্য করা আমার মাঝে মাঝে জিসি প্রভাবকে কমিয়ে দেয়।
সুপারক্যাট

11

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

আমি ব্যবহার করি IDisposable না করা সংস্থার পাশাপাশি থ্রেডগুলি সঠিকভাবে নিষ্পত্তি করা হয়েছে এমন জিনিসগুলি করতে করি।

স্কটের মন্তব্যের জবাবে সম্পাদনা :

কেবলমাত্র একবার যখন সিসি কলিজি (কল) কল করা হয় তখন একবার সিসি পারফরম্যান্স মেট্রিকগুলি প্রভাবিত হয় "

ধারণামূলকভাবে, জিসি অবজেক্ট রেফারেন্স গ্রাফের একটি দৃশ্য এবং থ্রেডের স্ট্যাক ফ্রেম থেকে সমস্ত রেফারেন্স বজায় রাখে। এই গাদাটি বেশ বড় এবং মেমরির অনেক পৃষ্ঠায় বিস্তৃত হতে পারে। অপ্টিমাইজেশন হিসাবে, জিসি তার পৃষ্ঠাগুলির বিশ্লেষণকে ক্যাচ করে যা অযথা পৃষ্ঠার পুনরুদ্ধার এড়াতে খুব ঘন ঘন পরিবর্তনের সম্ভাবনা নেই। কোনও পৃষ্ঠার ডেটা পরিবর্তিত হয়ে গেলে জিসি কার্নেল থেকে বিজ্ঞপ্তি গ্রহণ করে, তাই এটি জেনে যায় যে পৃষ্ঠাটি নোংরা এবং এর জন্য একটি পুনর্নির্মাণের প্রয়োজন। যদি সংগ্রহটি Gen0 এ থাকে তবে সম্ভবত পৃষ্ঠার অন্যান্য জিনিসগুলিও পরিবর্তিত হচ্ছে, তবে জেন 1 এবং জেন 2 তে এর সম্ভাবনা কম। উপহাসের দিক থেকে, এই প্ল্যাটফর্মটিতে সিলভারলাইট প্লাগ-ইন কাজ করার জন্য যে দল জিসি ম্যাককে পোর্ট করেছিলেন তাদের ম্যাক ওএস এক্সে এই হুকগুলি উপলব্ধ ছিল না।

সম্পদের অপ্রয়োজনীয় নিষ্পত্তি করার বিরুদ্ধে আরেকটি বিষয়: এমন পরিস্থিতিটি কল্পনা করুন যেখানে কোনও প্রক্রিয়া লোড হচ্ছে। এও ধারণা করুন যে প্রক্রিয়াটি কিছু সময়ের জন্য চলছে। সম্ভাবনাগুলি হ'ল সেই প্রক্রিয়াটির অনেকগুলি মেমরি পৃষ্ঠাগুলি ডিস্কে বদলানো হয়েছে। খুব কমপক্ষে তারা আর এল 1 বা এল 2 ক্যাশে নেই। এ জাতীয় পরিস্থিতিতে কোনও অ্যাপ্লিকেশন নেই যা এই সমস্ত ডেটা এবং কোড পৃষ্ঠাগুলিকে মেমরির মধ্যে 'রিলিজ' পুনরায় মেমোরিতে ফিরিয়ে আনবে যা প্রক্রিয়াটি শেষ হওয়ার পরে অপারেটিং সিস্টেম দ্বারা প্রকাশিত হবে। এটি পরিচালিত এবং এমনকি কিছু নিয়ন্ত্রণহীন সংস্থানগুলিতে প্রযোজ্য। কেবলমাত্র যে সংস্থানগুলি অ-পটভূমি থ্রেডগুলিকে বাঁচিয়ে রাখে তা নিষ্পত্তি করতে হবে, অন্যথায় প্রক্রিয়াটি জীবিত থাকবে।

এখন, সাধারণ সম্পাদনের সময় অল্পকালীন সংস্থান আছে যা নিয়ন্ত্রণহীন মেমরি ফাঁস এড়াতে অবশ্যই সঠিকভাবে পরিষ্কার করতে হবে (@ ফেজমনকি ডাটাবেস সংযোগগুলি, সকেটগুলি, উইন্ডো হ্যান্ডলগুলি নির্দেশ করে )। এই ধরণের জিনিসগুলি নিষ্পত্তি করতে হয়। যদি আপনি এমন কোনও শ্রেণি তৈরি করেন যা একটি থ্রেডের মালিকানাধীন (এবং মালিকানাধীন আমি বলতে চাইছি এটি এটি তৈরি করেছে এবং তাই এটি থামার বিষয়টি নিশ্চিত করার জন্য দায়বদ্ধ, কমপক্ষে আমার কোডিং শৈলীর মাধ্যমে), তবে সম্ভবত ক্লাসটি অবশ্যই IDisposableথ্রেডটি বাস্তবায়ন এবং ছিন্ন করতে হবেDispose

.NET ফ্রেমওয়ার্কটি IDisposableএই বর্গটি নিষ্পত্তি করতে হবে এমন বিকাশকারীদের জন্য একটি সংকেত এমনকি সতর্কতা হিসাবে ইন্টারফেস ব্যবহার করে । ফ্রেমওয়ার্কে এমন কোনও প্রকারের কথা ভাবতে পারি না যা কার্যকর করে IDisposable(স্পষ্ট ইন্টারফেস প্রয়োগগুলি বাদ দিয়ে) যেখানে নিষ্পত্তি optionচ্ছিক।


কলিং ডিসপোজ পুরোপুরি বৈধ, আইনী এবং উত্সাহিত। আইডিস্পোজেবল বাস্তবায়নকারী অবজেক্টগুলি সাধারণত কোনও কারণে এটি করে। জিসি.কলেক্ট () করা হলে কেবল একবার জিসি পারফরম্যান্স মেট্রিকগুলি প্রভাবিত হয়।
স্কট ডোরম্যান

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

1
হরফগুলির ক্ষেত্রে, আমার সন্দেহ হয় যে সমস্যাটি হ'ল মাইক্রোসফ্ট কখনই কোনও সংজ্ঞা দেওয়া "ফন্ট" অবজেক্টটি নিষ্পত্তি করার জন্য কোন সত্তা দায়বদ্ধ তা সত্যই নির্ধারণ করে না; কিছু ক্ষেত্রে, একটি নিয়ন্ত্রণগুলি একটি দীর্ঘস্থায়ী বস্তুর সাথে একটি ফন্ট ভাগ করতে পারে, তাই নিয়ন্ত্রণ থাকা ফন্টটি নিষ্পত্তি করা খারাপ। অন্যান্য ক্ষেত্রে, একটি ফন্ট একটি নিয়ন্ত্রণের জন্য বরাদ্দ করা হবে এবং অন্য কোথাও নেই, সুতরাং যদি নিয়ন্ত্রণ এটি নিষ্পত্তি না করে তবে কেউ তা করবে না। ঘটনাচক্রে, ফন্টগুলির সাথে এই সমস্যাটি এড়ানো যেত যদি একটি পৃথক নন-ডিসপোজেবল ফন্টটেম্পলেট শ্রেণি থাকত, কারণ নিয়ন্ত্রণগুলি তাদের ফন্টের জিডিআই হ্যান্ডেল ব্যবহার করে না বলে মনে হয়।
সুপারক্যাট

Callsচ্ছিকDispose() কলগুলির প্রসঙ্গে , দেখুন: stackoverflow.com/questions/913228/…
আরজে কুথবার্টসন

7

আপনি যে উদাহরণ পোস্ট করেছেন, এটি এখনও "এখনই স্মৃতি মুক্ত করে না"। সমস্ত স্মৃতি আবর্জনা সংগ্রহ করা হয়, তবে এটি স্মৃতিটিকে আগের প্রজন্মের মধ্যে সংগ্রহ করার অনুমতি দিতে পারে । নিশ্চিত হতে আপনাকে কিছু পরীক্ষা চালাতে হবে।


ফ্রেমওয়ার্ক ডিজাইনের গাইডলাইনগুলি হ'ল গাইডলাইন, এবং নিয়ম নয়। তারা আপনাকে জানায় যে ইন্টারফেসটি প্রাথমিকভাবে কী জন্য হয়, কখন এটি ব্যবহার করতে হয়, কীভাবে ব্যবহার করতে হয় এবং কখন এটি ব্যবহার না করে।

আমি একবার কোডটি পড়েছিলাম যা আইডিস্পোজেবল ব্যবহারে ব্যর্থতার জন্য একটি সহজ রোলব্যাক () ছিল। নীচের মিনিটেক্স ক্লাসটি ডিসপোজ () এ একটি পতাকা চেক করবে এবং যদি Commitকলটি কখনও না ঘটে তা তখন Rollbackনিজেই ডাকবে । এটি কল করার কোডটিকে বোঝার এবং বজায় রাখার জন্য আরও অনেক সহজ করার জন্য ইন্ডিয়ারেশনের একটি স্তর যুক্ত করেছে। ফলাফলটি এমন কিছু দেখাচ্ছে:

using( MiniTx tx = new MiniTx() )
{
    // code that might not work.

    tx.Commit();
} 

টাইমিং / লগিং কোডও একই কাজ করতে দেখেছি। এই ক্ষেত্রে ডিসপোজ () পদ্ধতিটি টাইমারটি বন্ধ করে দিয়েছিল এবং ব্লকটি বেরিয়ে এসেছিল logged

using( LogTimer log = new LogTimer("MyCategory", "Some message") )
{
    // code to time...
}

সুতরাং এখানে বেশ কয়েকটি কংক্রিটের উদাহরণ দেওয়া আছে যা কোনও ব্যবস্থাবিহীন রিসোর্স ক্লিনআপ না করে তবে ক্লিনার কোড তৈরি করতে সাফল্যের সাথে আইডিস্পোজেবল ব্যবহার করে।


উচ্চতর অর্ডার ফাংশনগুলি ব্যবহার করে @ ডানিয়েল এয়ারউইকারের উদাহরণটি একবার দেখুন। বেঞ্চমার্কিং, টাইমিং, লগিং ইত্যাদির জন্য এটি আরও সহজবোধ্য মনে হয়।
আলুয়ান হাদাদ


6

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

পাবলিক ক্লাস লার্জস্টফ
  আইডিপোজেবল কার্যকর করে
  স্ট্রিং হিসাবে ব্যক্তিগত _ লার্জ ()

  'কিছু অদ্ভুত কোড যার অর্থ _ লার্জটিতে এখন কয়েক মিলিয়ন দীর্ঘ স্ট্রিং রয়েছে।

  পাবলিক সাব ডিসপোজ () আইডিসপোজেবল কার্যকর করে is ডিসপোজ
    _Large = কিছুই
  শেষ সাব

আমি বুঝতে পারি যে ডিসপোজযোগ্য বাস্তবায়ন বর্তমান নির্দেশিকাগুলি অনুসরণ করে না, তবে আশা করি আপনি সমস্ত ধারণাটি পাবেন
এখন, যখন ডিসপোজ বলা হয়, কত স্মৃতি মুক্ত হয়?

উত্তর: কিছুই নেই।
কল ডিসপোজ অনিয়ন্ত্রিত সংস্থানগুলি মুক্তি দিতে পারে, এটি পরিচালিত স্মৃতি পুনরায় দাবি করতে পারে না, কেবল জিসি এটি করতে পারে। উপরের প্যাটার্ন অনুসরণ করা বাস্তবে এখনও একটি ভাল ধারণা, এটি বলার অপেক্ষা রাখে না যে উপরেরটি কোনও ভাল ধারণা নয়। একবার ডিসপোজ চালানো হয়ে গেলে, লার্জ স্টাফের উদাহরণটি সুযোগে থাকা সত্ত্বেও, লার্জ দ্বারা ব্যবহৃত মেমরির পুনরায় দাবি করার জন্য জিসি পুনরায় দাবি করা থামিয়ে দেয় না। _ লার্জের স্ট্রিংগুলি জেন ​​0 তেও হতে পারে তবে লার্জস্টফের উদাহরণটি জেন ​​2 হতে পারে, তাই আবারও, মেমরিটি খুব শীঘ্রই পুনরায় দাবি করা হবে।
যদিও উপরে প্রদর্শিত ডিসপোজ পদ্ধতিতে কল করতে চূড়ান্তকারী যুক্ত করার কোনও অর্থ নেই। এটি কেবল চূড়ান্ত দৌড়ানোর অনুমতি দেওয়ার জন্য মেমরির পুনঃ-দাবি দেরি করবে।


1
যদি উদাহরণটি LargeStuffজেনারেশন 2-তে এটি তৈরি করতে যথেষ্ট দীর্ঘ সময় _Largeধরে চলেছে এবং যদি জেনারেশন 0-এ থাকা একটি নতুন-নির্মিত স্ট্রিংয়ের একটি রেফারেন্স ধরে থাকে তবে যদি উদাহরণটি LargeStuffশূন্য না করে ছেড়ে দেওয়া হয় _Large, তবে স্ট্রিং দ্বারা উল্লেখ করা হয়েছে _Largeপরবর্তী জেন 2 সংগ্রহের আগ পর্যন্ত রাখা হবে। জিরো আউট _Largeকরার ফলে পরবর্তী জেন 0 সংগ্রহের স্ট্রিংটি মুছে ফেলা হতে পারে। বেশিরভাগ ক্ষেত্রে, উল্লেখগুলি বাতিল করা সহায়ক নয়, তবে এমন কিছু ক্ষেত্রে রয়েছে যেখানে এটি কিছু সুবিধা দিতে পারে offer
সুপারক্যাট

5

এছাড়াও নিয়ন্ত্রণ করতে একটি উপায় হিসেবে তার প্রাথমিক ব্যবহার থেকে সারা জীবনের এর সিস্টেম রিসোর্স (সম্পূর্ণরূপে এর সন্ত্রস্ত উত্তর দ্বারা আচ্ছাদিত ইয়ান , গৌরব!), IDisposable / ব্যবহার কম্বো এছাড়াও ব্যবহার করা যেতে পারে সুযোগ (সমালোচনামূলক) গ্লোবাল সম্পদ অবস্থা পরিবর্তন : কনসোল , থ্রেড , প্রক্রিয়া , কোনো বিশ্বব্যাপী বস্তুর একটি মত আবেদন উদাহরণস্বরূপ

আমি এই নিদর্শন সম্পর্কে একটি নিবন্ধ লিখেছি: http://pragmateek.com/c-scope-your-global-state-changes-with-idisposable-and-the- using-statement/

এটি চিত্রিত করে যে আপনি কীভাবে পুনরায় ব্যবহারযোগ্য এবং পঠনযোগ্য পদ্ধতিতে প্রায়শই ব্যবহৃত কিছু বিশ্বব্যাপী রাষ্ট্র রক্ষা করতে পারেন : কনসোল রঙ , বর্তমান থ্রেড সংস্কৃতি , এক্সেল অ্যাপ্লিকেশন অবজেক্ট বৈশিষ্ট্য ...


4

যদি কিছু থাকে তবে আমি কোডটি বাইরে রেখে যাওয়ার চেয়ে কম দক্ষ হওয়ার আশা করব ।

ক্লিয়ার () পদ্ধতিগুলি কল করা অপ্রয়োজনীয়, এবং ডিসপোজ এটি না করলে জিসি সম্ভবত তা করবে না ...


2

যে জিনিস হয় Dispose()অপারেশন উদাহরণ কোড যে করে পারে একটি সাধারণ জিসি কারণে প্রভাব যে ঘটবে না হবে আছে MyCollectionঅবজেক্ট।

দ্বারা উল্লিখিত অবজেক্ট যদি _theListবা _theDict, অন্যান্য বস্তু দ্বারা উল্লেখ করা হয় তারপর যে List<>বা Dictionary<>বস্তুর সংগ্রহে সাপেক্ষে হবে না কিন্তু হঠাৎ কোনো সামগ্রী থাকবে। উদাহরণস্বরূপ যদি কোনও ডিসপোজ () অপারেশন না ঘটে থাকে তবে those সংগ্রহগুলিতে এখনও তাদের বিষয়বস্তু থাকবে।

অবশ্যই, যদি এই অবস্থাটি হত তবে আমি এটিকে একটি ভাঙ্গা নকশা বলব - আমি কেবল ইঙ্গিত করছি (প্যাডেন্টিকালি, আমি মনে করি) যে Dispose()অপারেশনটি সম্পূর্ণরূপে অপ্রয়োজনীয় হতে পারে না, তার উপর নির্ভর করে এর অন্যান্য ব্যবহার রয়েছে কিনা তার উপর নির্ভর করেList<> বা Dictionary<>যে হয় না খণ্ডে প্রদর্শিত


তারা ব্যক্তিগত ক্ষেত্র, সুতরাং আমি মনে করি এটা ঠিক আছে যে ওপেন তাদের বিষয়ে রেফারেন্স দিচ্ছে না।
এমকিপিপি

1) কোড খণ্ডটি হ'ল উদাহরণ কোড, সুতরাং আমি কেবল উল্লেখ করছি যে এমন কোনও পার্শ্ব-প্রতিক্রিয়া থাকতে পারে যা উপেক্ষা করা সহজ; 2) বেসরকারী ক্ষেত্রগুলি প্রায়শই একটি গেটার সম্পত্তি / পদ্ধতির লক্ষ্য - সম্ভবত খুব বেশি (গেটার / সেটটারগুলি কিছু লোককে কিছুটা অ্যান্টি-প্যাটার্ন হিসাবে বিবেচনা করে)।
মাইকেল বুড়

2

"নিয়ন্ত্রণহীন সংস্থানসমূহ" সম্পর্কে বেশিরভাগ আলোচনার মধ্যে একটি সমস্যা হ'ল তারা সত্যিকার অর্থে এই শব্দটি সংজ্ঞায়িত করেন না, তবে বোঝাচ্ছেন যে এটির নিয়ন্ত্রণহীন কোডের সাথে কিছু করার আছে। যদিও এটি সত্য যে অবধি পরিচালিত সংস্থাগুলির অনেক ধরণের পরিচালনা ব্যবস্থাবিহীন কোডের সাথে ইন্টারফেস করা হয়, তবে এই জাতীয় শর্তে অপরিকল্পিত সংস্থান সম্পর্কে চিন্তাভাবনা সহায়ক নয়।

পরিবর্তে, সমস্তরূপে পরিচালিত সংস্থানসমূহের মধ্যে যা কিছু রয়েছে তা স্বীকৃতি দেওয়া উচিত: তারা সকলে তার পক্ষে কিছু বাইরে বাইরে 'জিনিস' করার জন্য কিছু অন্য কিছু 'জিনিসের' ক্ষয়ক্ষতির জন্য এবং অন্য সংস্থা যখন পর্যন্ত এটি করতে সম্মত হয় তখন কোনও বস্তুকে প্ররোচিত করে পরবর্তী ঘোষণা. যদি অবজেক্টটি কোনও চিহ্ন ছাড়াই পরিত্যাগ করা এবং মুছে ফেলা হয় তবে কিছুই 'বাইরের' জিনিসটিকে কখনও বলতে পারে না যে বস্তুর পক্ষে এটির আর আচরণের পরিবর্তন করার দরকার নেই যা আর নেই; ফলস্বরূপ, 'জিনিসটির কার্যকারিতা স্থায়ীভাবে হ্রাস পাবে।

তারপরে একটি অপরিবর্তিত সংস্থানটি কোনও বস্তুর পক্ষে তার আচরণগত পরিবর্তন করতে কিছু বাহিরের 'জিনিস' দ্বারা একটি চুক্তির প্রতিনিধিত্ব করে, যা যদি বস্তুটি পরিত্যাগ করা এবং অস্তিত্ব বন্ধ করে দেওয়া হয় তবে সেই বাহিরের 'জিনিস' এর কার্যকারিতা ব্যাহত হয়। পরিচালিত সংস্থান হ'ল এমন একটি বস্তু যা এই জাতীয় চুক্তির সুবিধাভোগী, তবে যা পরিত্যাগ করা হলে বিজ্ঞপ্তিটি পেতে সাইন আপ করেছে এবং যা ধ্বংস হওয়ার আগে এই বিষয়টিকে তার ব্যবস্থা রাখার জন্য এই জাতীয় বিজ্ঞপ্তি ব্যবহার করবে।


ঠিক আছে, আইএমও, অব্যবস্থাপনাযুক্ত বিষয়ের সংজ্ঞা পরিষ্কার; যে কোনও নন-জিসি অবজেক্ট
ইওনিল

1
@ ইওনিল: নিয়ন্ত্রণহীন অবজেক্ট! = পরিচালনা না করা রিসোর্স। ইভেন্টগুলির মতো বিষয়গুলি পুরোপুরি পরিচালিত বস্তুগুলি ব্যবহার করে প্রয়োগ করা যেতে পারে তবে এটি পরিচালনা না করা সংস্থানগুলি তৈরি করে কারণ - কমপক্ষে দীর্ঘকালীন-অবজেক্টের ইভেন্টগুলিতে সাবস্ক্রাইব করা স্বল্পস্থায়ী বস্তুর ক্ষেত্রে - জিসি সেগুলি কীভাবে পরিষ্কার করবেন সে সম্পর্কে কিছুই জানেন না them ।
সুপারক্যাট


2

সংজ্ঞা প্রথম। আমার জন্য অব্যবস্থাপিত সংস্থান বলতে কিছু শ্রেণি বোঝায় যা আইডিপোজেবল ইন্টারফেস বা ডিএল-তে কল ব্যবহারের মাধ্যমে তৈরি কিছু প্রয়োগ করে। এই জাতীয় অবজেক্টগুলি কীভাবে মোকাবেলা করতে হয় তা জিসি জানে না। যদি ক্লাসে উদাহরণস্বরূপ কেবল মান ধরণের থাকে তবে আমি এই শ্রেণিকে পরিচালনাবিহীন সংস্থান সহ শ্রেণি হিসাবে বিবেচনা করি না। আমার কোডের জন্য আমি পরবর্তী অনুশীলনগুলি অনুসরণ করি:

  1. আমার দ্বারা নির্মিত শ্রেণি যদি কিছু পরিচালনা না করা সংস্থান ব্যবহার করে তবে এর অর্থ হ'ল মেমরি পরিষ্কার করার জন্য আমার আইডিপসোয়েবল ইন্টারফেসও প্রয়োগ করা উচিত।
  2. আমি এর ব্যবহার শেষ হওয়ার সাথে সাথে অবজেক্টগুলি পরিষ্কার করুন।
  3. আমার নিষ্পত্তি পদ্ধতিতে আমি ক্লাসের সমস্ত আইডিস্পোজেবল সদস্য এবং পুনরুদ্ধার কল করি।
  4. আমার নিষ্পত্তি পদ্ধতিতে জঞ্জাল সংগ্রাহককে অবহিত করার জন্য GC.SuppressFinalize (এটি) কল করুন যে আমার বস্তুটি ইতিমধ্যে পরিষ্কার হয়ে গেছে। আমি এটি করি কারণ জিসি কল করা ব্যয়বহুল অপারেশন।
  5. অতিরিক্ত সতর্কতা হিসাবে আমি ডিসপোজ () এর একাধিকবার কল করার চেষ্টা করি।
  6. কিছু সময় আমি প্রাইভেট সদস্য যুক্ত করলাম _বিক্রয়যুক্ত এবং চেক ইন পদ্ধতি কলগুলি কী অবজেক্টটি পরিষ্কার হয়েছিল। এবং যদি এটি পরিষ্কার হয়ে যায় তবে অবজেক্ট ডিসপোজড এক্সেক্সেশন উত্পন্ন করুন
    নিম্নলিখিত টেমপ্লেটটি কোডের নমুনা হিসাবে আমি শব্দগুলিতে বর্ণিত কি তা দেখায়:

public class SomeClass : IDisposable
    {
        /// <summary>
        /// As usually I don't care was object disposed or not
        /// </summary>
        public void SomeMethod()
        {
            if (_disposed)
                throw new ObjectDisposedException("SomeClass instance been disposed");
        }

        public void Dispose()
        {
            Dispose(true);
        }

        private bool _disposed;

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;
            if (disposing)//we are in the first call
            {
            }
            _disposed = true;
        }
    }

1
"আমার জন্য অপরিশোধিত সংস্থান বলতে কিছু শ্রেণি বোঝায় যা আইডিপোজেবল ইন্টারফেস বা ডেলির জন্য কল ব্যবহারের মাধ্যমে তৈরি করা কিছু প্রয়োগ করে।" সুতরাং আপনি বলছেন যে যে কোনও ধরণের যা is IDisposableনিজেই একটি নিয়ন্ত্রণহীন সংস্থান হিসাবে বিবেচনা করা উচিত? এটি সঠিক বলে মনে হচ্ছে না। এছাড়াও যদি প্ররোচিতকরণটি খাঁটি মানের ধরণের হয় তবে আপনি মনে করেন যে এটির নিষ্পত্তি করার দরকার নেই। এটিও ভুল বলে মনে হচ্ছে।
আলুয়ান হাদ্দাদ

প্রত্যেকে নিজেরাই বিচার করে। আমি শুধু যুক্ত করার জন্য আমার কোডে কিছু যুক্ত করতে চাই না। এর অর্থ যদি আমি আইডিস্পোজেবল যুক্ত করি তবে এর অর্থ হ'ল আমি এমন একধরণের কার্যকারিতা তৈরি করেছি যা জিসি পরিচালনা করতে পারে না বা আমি মনে করি এটি তার আজীবন সঠিকভাবে পরিচালনা করতে সক্ষম হবে না।
ইউরি জালেটস্কি

2

আপনার প্রদত্ত কোড নমুনা IDisposableব্যবহারের জন্য ভাল উদাহরণ নয় । সাধারণত ডিকশনারি ক্লিয়ারিং Disposeপদ্ধতিতে যাওয়া উচিত নয় । অভিধান আইটেমগুলি সুযোগের বাইরে চলে গেলে সাফ হয়ে যায় এবং নিষ্পত্তি করা হবে। IDisposableবাস্তবায়নের জন্য এমন কিছু মেমরি / হ্যান্ডলারগুলি মুক্ত করতে হবে যা সুযোগের বাইরে থাকার পরেও মুক্তি / মুক্ত করবে না।

নিম্নলিখিত কোডটি কিছু কোড এবং মন্তব্যে আইডিজিপোজযোগ্য প্যাটার্নের জন্য একটি ভাল উদাহরণ দেখায়।

public class DisposeExample
{
    // A base class that implements IDisposable. 
    // By implementing IDisposable, you are announcing that 
    // instances of this type allocate scarce resources. 
    public class MyResource: IDisposable
    {
        // Pointer to an external unmanaged resource. 
        private IntPtr handle;
        // Other managed resource this class uses. 
        private Component component = new Component();
        // Track whether Dispose has been called. 
        private bool disposed = false;

        // The class constructor. 
        public MyResource(IntPtr handle)
        {
            this.handle = handle;
        }

        // Implement IDisposable. 
        // Do not make this method virtual. 
        // A derived class should not be able to override this method. 
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method. 
            // Therefore, you should call GC.SupressFinalize to 
            // take this object off the finalization queue 
            // and prevent finalization code for this object 
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios. 
        // If disposing equals true, the method has been called directly 
        // or indirectly by a user's code. Managed and unmanaged resources 
        // can be disposed. 
        // If disposing equals false, the method has been called by the 
        // runtime from inside the finalizer and you should not reference 
        // other objects. Only unmanaged resources can be disposed. 
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called. 
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources. 
                if(disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }

                // Call the appropriate methods to clean up 
                // unmanaged resources here. 
                // If disposing is false, 
                // only the following code is executed.
                CloseHandle(handle);
                handle = IntPtr.Zero;

                // Note disposing has been done.
                disposed = true;

            }
        }

        // Use interop to call the method necessary 
        // to clean up the unmanaged resource.
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private extern static Boolean CloseHandle(IntPtr handle);

        // Use C# destructor syntax for finalization code. 
        // This destructor will run only if the Dispose method 
        // does not get called. 
        // It gives your base class the opportunity to finalize. 
        // Do not provide destructors in types derived from this class.
        ~MyResource()
        {
            // Do not re-create Dispose clean-up code here. 
            // Calling Dispose(false) is optimal in terms of 
            // readability and maintainability.
            Dispose(false);
        }
    }
    public static void Main()
    {
        // Insert code here to create 
        // and use the MyResource object.
    }
}

1

পরিচালিত সংস্থানগুলি নিষ্পত্তি করার জন্য সবচেয়ে ন্যায়সঙ্গত ব্যবহারের ক্ষেত্রে হ'ল জিসি রিসোর্সগুলি দাবি করার জন্য প্রস্তুত যা অন্যথায় কখনই সংগ্রহ করা হয় না।

একটি প্রধান উদাহরণ বৃত্তাকার উল্লেখ।

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

এটির একমাত্র উপায় হ'ল মাতাপিতা উল্লেখগুলি বাচ্চাদের উপর নালার জন্য সেট করে ম্যানুয়ালি বৃত্তাকার রেফারেন্সগুলি ভঙ্গ করা।

অভিভাবক এবং শিশুদের ক্ষেত্রে আইডিস্পোজেবল কার্যকর করা এটির সর্বোত্তম উপায়। যখন পিতামাতার কাছে ডিসপোজ আহ্বান করা হয়, তখন সমস্ত শিশুদের উপর ডিসপোজ কল করুন এবং শিশু ডিসপোজ পদ্ধতিতে পিতামাতার উল্লেখগুলি বাতিল করে দিন।


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

1

আমি দেখতে পাচ্ছি যে অনেকগুলি উত্তর পরিচালিত এবং অপরিশোধিত উভয় সংস্থার জন্য আইডিসপোজেবল ব্যবহারের বিষয়ে কথা বলার স্থান পরিবর্তন করেছে। আমি এই নিবন্ধটিকে সর্বোত্তম ব্যাখ্যা হিসাবে একটি হিসাবে পরামর্শ দেব যা আমি সনাক্ত করতে পারি যে কীভাবে আইডিস্পোসেসযোগ্যটি ব্যবহার করা উচিত।

https://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About

আসল প্রশ্নের জন্য; আপনার যদি ম্যানেজ করা অবজেক্টগুলিকে পরিষ্কার করতে আইডিস্পোজেবল ব্যবহার করা উচিত যা সংক্ষিপ্ত উত্তরটি হ'ল না । কারণটি হ'ল একবার আপনি যদি কোনও আইডিস্পোজেবল ডিসপোজ করেন তখন আপনার এটিকে সুযোগের বাইরে যেতে দেওয়া উচিত। সেই সময়ে কোনও রেফারেন্স প্রাপ্ত শিশু অবজেক্টগুলিও সুযোগের বাইরে থাকে এবং সংগ্রহ করা হবে।

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


1
কোনও উত্তর কেন আপনার উত্তর -1 এছিল তা আমি বুঝতে পারি নি
সেবাস্তিয়ান অস্কার লোপেজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.