ইভেন্ট হ্যান্ডলারের মেমরি ফাঁস কেন এবং কীভাবে এড়ানো যায়?


154

আমি কেবল স্ট্যাকওভারফ্লোতে কিছু প্রশ্ন ও উত্তর পড়ে বুঝতে পেরেছি যে +=সি # (অথবা আমার ধারণা, অন্যান্য নেট ভাষাগুলি) ব্যবহার করে ইভেন্ট হ্যান্ডলার যুক্ত করা সাধারণ মেমরি ফাঁসের কারণ হতে পারে ...

আমি অতীতে বহুবার ইভেন্ট হ্যান্ডলারগুলি ব্যবহার করেছি এবং কখনই বুঝতে পারি নি যে তারা আমার অ্যাপ্লিকেশনগুলিতে মেমরির ফাঁস হতে পারে বা ঘটায়।

এটি কীভাবে কাজ করে (অর্থাত্ এটি কেন স্মৃতি ফাঁস হয়)?
আমি কিভাবে এই সমস্যা ঠিক করতে পারবো ? -=একই ইভেন্ট হ্যান্ডলারটি কি যথেষ্ট ব্যবহার করছেন?
এই জাতীয় পরিস্থিতি পরিচালনা করার জন্য কি সাধারণ নকশার ধরণগুলি বা সেরা অনুশীলন রয়েছে?
উদাহরণ: আমি ইউআই-তে বিভিন্ন ইভেন্ট উত্থাপন করতে বিভিন্ন ইভেন্ট ইভেন্ট হ্যান্ডলার ব্যবহার করে অনেকগুলি বিভিন্ন থ্রেডযুক্ত একটি অ্যাপ্লিকেশন কীভাবে পরিচালনা করব?

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

উত্তর:


188

কারণটি ব্যাখ্যা করা সহজ: ইভেন্ট ইভেন্ট হ্যান্ডলার সাবস্ক্রাইব হওয়ার সময় ইভেন্টটির প্রকাশক গ্রাহককে ইভেন্ট হ্যান্ডলার প্রতিনিধিটির মাধ্যমে একটি রেফারেন্স রাখেন (ডেলিগেট একটি উদাহরণ পদ্ধতি হিসাবে ধরে নেওয়া)।

প্রকাশক যদি গ্রাহকের চেয়ে বেশি দিন বেঁচে থাকেন তবে গ্রাহকের অন্য কোনও উল্লেখ না থাকলেও এটি গ্রাহককে বাঁচিয়ে রাখবে।

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

এটা তোলে হয় একটি সম্ভাব্য কারণ ... কিন্তু আমার অভিজ্ঞতা বরং এটা ওভার কৃত্রিম উপায়ে উত্তেজিত করে। আপনার মাইলেজ অবশ্যই আলাদা হতে পারে ... আপনার অবশ্যই যত্নবান হওয়া দরকার।


... আমি কিছু লোককে "নেট মধ্যে সর্বাধিক সাধারণ মেমরির ফাঁস" এর মতো প্রশ্নের উত্তরে এই সম্পর্কে লিখতে দেখেছি।
গিলিব

32
প্রকাশকের পক্ষ থেকে এটিকে ঘুরিয়ে নেওয়ার একটি উপায় হ'ল ইভেন্টটি বাতিল হয়ে যাওয়ার পরে আপনি নিশ্চিত হন যে আপনি আর এটিকে চালিত করবেন না। এটি সুস্পষ্টভাবে সমস্ত গ্রাহককে সরিয়ে ফেলবে, এবং কার্যকর হতে পারে যখন নির্দিষ্ট ইভেন্টগুলি কেবলমাত্র বস্তুর জীবদ্দশায় কিছু নির্দিষ্ট সময়ে চালিত হয়।
জেএসবি ձոգչ

2
অনুষ্ঠানটি শূন্য করার জন্য ডিপোজ পদ্ধতিটি একটি ভাল মুহুর্ত হবে
ডেভি ফামেঙ্গি

6
@ ডেভিফিয়ামেঝি: আচ্ছা, যদি কোনও কিছু নিষ্পত্তি করা হয় তবে এটি কমপক্ষে একটি সম্ভবত ইঙ্গিত দেয় যে এটি খুব শীঘ্রই আবর্জনা সংগ্রহের জন্য যোগ্য হতে চলেছে, সেই সময়ে সেখানে গ্রাহকরা কী তা বিবেচ্য নয়।
জন স্কিটি

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

12

হ্যাঁ, -=যথেষ্ট However (বিস্তারিত জানার জন্য জনের পোস্ট দেখুন)। ডিজাইনের প্যাটার্ন সম্পর্কিত, দুর্বল ইভেন্ট প্যাটার্নটি একবার দেখুন



যদি আমি জানি যে কোনও প্রকাশক গ্রাহকের চেয়ে বেশি দিন বেঁচে আছেন, আমি গ্রাহককে IDisposableইভেন্টটি থেকে সাবস্ক্রাইব করে দেব ।
শিমি ওয়েটজ্যান্ডলার

9

এই বিভ্রান্তিটি আমি https://www.spicelogic.com/Blog/net-event-handler-memory-leak-16 এ ব্যাখ্যা করেছি । আমি এখানে সংক্ষিপ্ত করার চেষ্টা করব যাতে আপনি একটি পরিষ্কার ধারণা পেতে পারেন।

রেফারেন্স অর্থ, "প্রয়োজন":

প্রথমত, আপনার বুঝতে হবে যে, যদি বস্তু এ এর ​​সাথে বস্তু বিয়ের একটি রেফারেন্স থাকে, তবে এর অর্থ হবে, অবজেক্ট এ কাজ করতে বস্তুর বি দরকার, তাই না? সুতরাং, আবর্জনা সংগ্রহকারী অবজেক্ট বিটি সংগ্রহ করবে না যতক্ষণ না বস্তু এ স্মৃতিতে বেঁচে থাকবে।

আমি মনে করি এই অংশটি কোনও বিকাশকারীর কাছে সুস্পষ্ট হওয়া উচিত।

+ = মানে, বাম বস্তুতে ডান দিকের বস্তুর রেফারেন্স ইনজেকশন:

তবে, বিভ্রান্তিটি সি # + = অপারেটর থেকে আসে। এই অপারেটরটি বিকাশকারীকে পরিষ্কারভাবে জানায় না যে, এই অপারেটরের ডান হাতটি আসলে বাম-হাতের বস্তুর একটি রেফারেন্স ইনজেক্ট করছে।

এখানে চিত্র বর্ণনা লিখুন

এবং এটি করার মাধ্যমে, বস্তু এ মনে করে, এটিতে অবজেক্ট বিটি প্রয়োজন, যদিও আপনার দৃষ্টিকোণ থেকে, অবজেক্ট এ এর ​​বস্তু বি বাঁচে কি না সেদিকে নজর দেওয়া উচিত নয়। যেহেতু বস্তু A মনে করে অবজেক্ট B এর প্রয়োজনীয়, অবজেক্ট এ অবজেক্ট B কে আবর্জনা সংগ্রাহকের হাত থেকে রক্ষা করে যতক্ষণ অবজেক্ট এ জীবিত থাকে। তবে, যদি আপনি ইভেন্টটির গ্রাহক অবজেক্টটিকে দেওয়া সুরক্ষাটি না চান, তবে আপনি বলতে পারেন, একটি মেমরি ফাঁস হয়েছিল।

এখানে চিত্র বর্ণনা লিখুন

ইভেন্ট হ্যান্ডলারটিকে আলাদা করে আপনি এ জাতীয় ফুটো এড়াতে পারেন।

কীভাবে সিদ্ধান্ত নেবেন?

তবে, আপনার পুরো কোড-বেসে প্রচুর ইভেন্ট এবং ইভেন্ট হ্যান্ডলার রয়েছে। এর অর্থ কি, আপনার সর্বত্র ইভেন্ট হ্যান্ডলারদের আলাদা করা দরকার? উত্তরটি হ'ল যদি আপনার এটি করতে হয় তবে আপনার কোডবেসটি ভার্বোজের সাথে সত্যই কুরুচিপূর্ণ হবে।

আপনি কোনও বিচ্ছিন্ন ইভেন্ট হ্যান্ডলার প্রয়োজনীয় কিনা তা নির্ধারণ করতে আপনি বরং একটি সাধারণ ফ্লো চার্ট অনুসরণ করতে পারেন।

এখানে চিত্র বর্ণনা লিখুন

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

এমন একটি দৃশ্যের উদাহরণ যেখানে আপনাকে চিন্তার দরকার নেই

উদাহরণস্বরূপ, উইন্ডোর একটি বাটন ক্লিক ইভেন্ট।

এখানে চিত্র বর্ণনা লিখুন

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

একটি ইভেন্ট হ্যান্ডলার বিচ্ছিন্নতা আবশ্যক যখন একটি উদাহরণ।

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

এখানে চিত্র বর্ণনা লিখুন

এবং, শিশু উইন্ডোটি মূল উইন্ডোটির একটি ইভেন্টে সদস্যতা নিয়েছে।

এখানে চিত্র বর্ণনা লিখুন

এই কোড থেকে, আমরা পরিষ্কারভাবে বুঝতে পারি যে মূল উইন্ডোতে একটি বোতাম আছে। সেই বোতামটি ক্লিক করা একটি শিশু উইন্ডো প্রদর্শন করে। সন্তানের উইন্ডোটি মূল উইন্ডো থেকে একটি ইভেন্ট শোনায়। কিছু করার পরে, ব্যবহারকারী সন্তানের উইন্ডোটি বন্ধ করে দেয়।

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

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

মেমরির প্রোফাইলার ব্যবহার করে ধারণাটির প্রমাণ।

আমরা মেমরির প্রোফাইলার দিয়ে ধারণাটি বৈধ করতে না পারলে এটি খুব মজাদার হবে না। আমি এই পরীক্ষায় জেটব্রেইন ডটমেমরি প্রোফাইলার ব্যবহার করেছি।

প্রথমত, আমি মেইন উইন্ডো চালিয়েছি, যা এটির মতো দেখায়:

এখানে চিত্র বর্ণনা লিখুন

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

এখানে চিত্র বর্ণনা লিখুন

ঠিক আছে, তারপরে, আমি নীচের চিত্রের মতো ইভেন্ট হ্যান্ডলারটিকে বিযুক্ত করেছি।

এখানে চিত্র বর্ণনা লিখুন

তারপরে, আমি একই পদক্ষেপগুলি সম্পাদন করেছি এবং মেমরি প্রোফাইলারটি পরীক্ষা করেছি। এবার, বাহ! আর মেমরি ফুটো নেই।

এখানে চিত্র বর্ণনা লিখুন


3

একটি ইভেন্ট হ'ল ইভেন্ট হ্যান্ডলারের একটি লিঙ্কযুক্ত তালিকা

আপনি যখন ইভেন্টটিতে + = নতুন ইভেন্টহ্যান্ডলারটি করেন তবে এই বিশেষ ফাংশনটি শ্রোতারূপে আগে যুক্ত করা হয়েছে কিনা তা আসলেই কিছু আসে যায় না, এটি প্রতি + = একবার যোগ হবে।

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

এখানে দেখো

এবং এমএসডিএন এখানে


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