নিষ্পত্তি করার বিষয়টি হ'ল পরিচালনাহীন সংস্থানগুলি মুক্ত করা। এটি কোনও পর্যায়ে করা দরকার, অন্যথায় সেগুলি কখনই পরিষ্কার করা হবে না। আবর্জনা সংগ্রহকারী কোনও প্রকারের পরিবর্তনে কীভাবে কল করতে জানেন তা জানেন না, এটি কল করার দরকার আছে কিনা তা তা জানেন না ।DeleteHandle()
IntPtr
DeleteHandle()
দ্রষ্টব্য : একটি অপরিকল্পিত সংস্থান কী? যদি আপনি এটি মাইক্রোসফ্ট। নেট ফ্রেমওয়ার্কে খুঁজে পান: এটি পরিচালিত। আপনি যদি এমএসডিএন ঘুরে বেড়াতে যান তবে এটি নিয়ন্ত্রণহীন। .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 পৃষ্ঠাগুলি সুস্পষ্ট এবং মাইক্রোসফ্টের বাস্তবায়নের বিশদটি রয়েছে।
আমি মনে করি যে প্রতিটি প্রোগ্রামার যিনি কখনও অবজেক্টস বা সিওএম নিয়ে কাজ করেছেন তাদের খুব কমপক্ষে প্রথম অধ্যায়টি পড়া উচিত। এটি যে কোনও কিছুর সেরা ব্যাখ্যা।
অতিরিক্ত বোনাস পড়া
যখন আপনি জানেন সমস্ত কিছু যখন এরিক লিপার্ট ভুল করে
সুতরাং সঠিক চূড়ান্তকরণকারীটি লেখা সত্যিই খুব কঠিন এবং আমি আপনাকে যে সেরা পরামর্শ দিতে পারি তা হল চেষ্টা না করা ।