টিপিএল টাস্ক অবজেক্টে ডিসপোজ () কল না করা কি গ্রহণযোগ্য বলে বিবেচিত হয়?


123

আমি একটি পটভূমি থ্রেড চালানোর জন্য একটি কাজ ট্রিগার করতে চাই। আমি কাজগুলি সমাপ্তির জন্য অপেক্ষা করতে চাই না।

নেট 3.5 এ আমি এটি করতাম:

ThreadPool.QueueUserWorkItem(d => { DoSomething(); });

.NET 4-এ টিপিএল প্রস্তাবিত উপায়। আমি যে সাধারণ প্যাটার্নটি সুপারিশ করেছি তা হ'ল:

Task.Factory.StartNew(() => { DoSomething(); });

যাইহোক, StartNew()পদ্ধতিটি Taskকার্যকর করে এমন একটি বস্তু প্রদান করে IDisposable। এটি এই প্যাটার্নটির পরামর্শ দেয় এমন লোকদের দ্বারা এটি উপেক্ষা করা হবে বলে মনে হয়। Task.Dispose()পদ্ধতিটিতে এমএসডিএন ডকুমেন্টেশন বলে:

"আপনি কার্যটিতে আপনার শেষ উল্লেখটি প্রকাশের আগে সর্বদা ডিসপোজকে কল করুন" "

কোনও কাজ শেষ না হওয়া পর্যন্ত আপনি ডিসপোজ কল করতে পারবেন না, সুতরাং মূল থ্রেড ওয়েট এবং কল ডিসপোজ করা প্রথম স্থানে একটি পটভূমির থ্রেডে করার পয়েন্টকে পরাস্ত করবে। এমন কোনও সমাপ্ত / সমাপ্ত ইভেন্ট বলে মনে হয় না যা পরিষ্কার করার জন্য ব্যবহার করা যেতে পারে।

টাস্ক ক্লাসের এমএসডিএন পৃষ্ঠাটি এতে মন্তব্য করে না, এবং "প্রো সি # 2010 ..." বইটি একই প্যাটার্নের প্রস্তাব দেয় এবং টাস্ক নিষ্পত্তি সম্পর্কে কোনও মন্তব্য করে না।

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

সুতরাং আমার প্রশ্নগুলি হ'ল:

  • Dispose()এক্ষেত্রে Taskক্লাসে ফোন না করা কি গ্রহণযোগ্য ? এবং যদি তা হয় তবে কেন এবং এর ঝুঁকি / ফলাফল রয়েছে?
  • এটি নিয়ে যে কোনও ডকুমেন্টেশন রয়েছে তা কি আলোচনা করে?
  • অথবা Taskযে জিনিসটি আমি মিস করেছি তা নিষ্পত্তি করার কোনও উপযুক্ত উপায় আছে ?
  • নাকি টিপিএলের সাথে ফায়ার ও ভুলে যাওয়া কাজের অন্য কোনও উপায় আছে?

উত্তর:


108

এমএসডিএন ফোরামে এটি নিয়ে একটি আলোচনা রয়েছে ।

মাইক্রোসফ্ট পিএফএক্স দলের সদস্য স্টিফেন টুব এই কথাটি বলেছেন:

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

আপডেট (অক্টোবর ২০১২)
স্টিফেন টুব আমাকে কি টাস্কগুলি নিষ্পত্তি করতে হবে শিরোনামে একটি ব্লগ পোস্ট করেছেন ? যা আরও কিছু বিশদ দেয় এবং নেট .৪.৪-এর উন্নতি ব্যাখ্যা করে।

সংক্ষিপ্তসার: আপনার Task99% সময় অবজেক্টগুলি নিষ্পত্তি করার দরকার নেই ।

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

  1. নেট 4.5 হিসাবে, কেবলমাত্র যখন কোনও Taskঅভ্যন্তরীণ অপেক্ষার হ্যান্ডেল বরাদ্দ করে ( Taskঅবজেক্টের একমাত্র পরিচালনাহীন সংস্থান ) আপনি যখন স্পষ্টভাবে এইটির ব্যবহার IAsyncResult.AsyncWaitHandleকরেন Task, এবং
  2. Taskবস্তু নিজেই একটি finalizer নেই; হ্যান্ডেলটি নিজেই একটি চূড়ান্তকরণকারীর সাথে কোনও বস্তুতে আবৃত থাকে, সুতরাং যদি এটি বরাদ্দ না করা হয় তবে চালানোর জন্য কোনও ফাইনালাইজার নেই।

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

প্রকৃতপক্ষে, আমি কেবল লক্ষ্য করেছি যে এই থ্রেডের উত্তরদাতা প্রকৃতপক্ষে মাইক্রোসফ্টে কাজ করে, আপাতদৃষ্টিতে পিএফএক্স টিমে কাজ করে, সুতরাং আমি মনে করি এটি একটি সরকারী উত্তর। তবে এর নীচের দিকে পরামর্শ রয়েছে যে এটি সব ক্ষেত্রেই কাজ করে না। যদি কোনও সম্ভাব্য ফুটা থাকে তবে আমি কি থ্রেডপুলে ফিরে যাওয়ার চেয়ে ভাল? কিউ ইউজার ওয়ার্ক আইটেমটি জানি যা নিরাপদ?
সাইমন পি স্টিভেনস

হ্যাঁ, এটি খুব আশ্চর্যজনক যে এখানে একটি ডিসপোজ রয়েছে যা আপনি কল করতে পারেন না। আপনি যদি এখানে নমুনাগুলি একবার দেখে থাকেন তবে এমএসডিএন.মাইক্রোসফটকম /en-us/library/dd537610.aspx এবং এখানে এমএসডিএন.মিকাইক্রোসফট /en-us/library/dd537609.aspx তারা কাজগুলি নিষ্পত্তি করছে না। তবে এমএসডিএন-তে কোড নমুনাগুলি কখনও কখনও খুব খারাপ কৌশলগুলি প্রদর্শন করে। এছাড়াও প্রশ্নের উত্তর দেওয়া লোকটি মাইক্রোসফ্টের পক্ষে কাজ করে।
কিরিল মুজিকভ

2
@ সিমন: (১) আপনি যে এমএসডিএন ডকটি উদ্ধৃত করেছেন তা হ'ল জেনেরিক পরামর্শ, নির্দিষ্ট ক্ষেত্রে আরও সুনির্দিষ্ট পরামর্শ থাকে (যেমন ইউআই থ্রেডে কোড চালানোর জন্য EndInvokeউইনফোর্মে ব্যবহার BeginInvokeকরার প্রয়োজন নেই)। (২) স্টিফেন টুব পিএফএক্সের কার্যকর ব্যবহার সম্পর্কে নিয়মিত স্পিকার হিসাবে বেশ ভাল জানেন (যেমন চ্যানেল 9.msdn.com- এ ), সুতরাং যে কেউ যদি ভাল দিকনির্দেশনা দিতে পারে তবে সে তা হয়। তার দ্বিতীয় অনুচ্ছেদটি নোট করুন: এমন সময় রয়েছে যখন চূড়ান্তকরণকারীকে জিনিস রেখে দেওয়া ভাল।
রিচার্ড

12

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

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

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


6
তবে কোনও কাজ Threadবেশিরভাগ ক্ষেত্রেই তৈরি করে না , এটি থ্রেডপুল ব্যবহার করে।
সুইউক

-1

আমি এই পোস্টে দেখানো কৌশলটিতে কাউকে ওজন দেখতে দেখতে পছন্দ করব: টাইপসেফ ফায়ার অ্যান্ড-ভুলে সি সি # তে অ্যাসিনক্রোনাস ডেলিগেটের প্রার্থনা

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

public static void FireAndForget<T>(this Action<T> act,T arg1)
{
    var tsk = Task.Factory.StartNew( ()=> act(arg1),
                                     TaskCreationOptions.LongRunning);
    tsk.ContinueWith(cnt => cnt.Dispose());
}

3
অবশ্যই তা Taskফিরিয়ে দেওয়া উদাহরণটি নিষ্পত্তি করতে ব্যর্থ হয়েছে ContinueWith, তবে স্টিফেন টুবের উদ্ধৃতিটি গ্রহণযোগ্য উত্তর: যদি কোনও কাজ কোনও কাজ আটকে না রাখে তবে নিষ্পত্তি করার কিছুই নেই।
রিচার্ড

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

1
সুতরাং এটি হিসাবে চালিয়ে যাওয়া চালিয়ে যাওয়া কোডটি আসলে রিডান্টেন্টের চেয়ে খারাপ কারণ এটি কেবলমাত্র পুরানো কাজটি নিষ্পত্তি করার জন্য আরেকটি কাজ তৈরি করতে সক্ষম হবে। যেভাবে এটি দাঁড়ায় এটি মূলত এই কোড ব্লকটিতে কোনও ব্লকিং ওয়েট প্রবর্তন করা সম্ভব হবে না যদি আপনি যে ক্রিয়াকলাপের প্রতিনিধি এতে উত্তীর্ণ হয়েছিলেন তাও নিজেই কার্য সম্পাদন করার চেষ্টা করছেন?
ক্রিস মেরিসিক

1
দ্বিতীয় কার্যের যত্ন নেওয়ার জন্য আপনি কীভাবে ল্যাম্বডাস ভেরিয়েবলকে কিছুটা জটিল পদ্ধতিতে ক্যাপচার করতে সক্ষম হতে পারেন। Task disper = null; disper = tsk.ContinueWith(cnt => { cnt.Dispose(); disper.Dispose(); });
গিদিওন এঞ্জেলবার্থ

আপাতদৃষ্টিতে কাজ করতে হবে এমন জিডিয়ন এঞ্জেলবার্থ যেহেতু ডিসির ডিসপ্লে কখনই জিসির দ্বারা নিষ্পত্তি করা উচিত নয় ল্যাম্বডা নিজেকে নিষ্পত্তি করার জন্য অনুরোধ না করা অবধি সেখানে বৈধ থাকতে হবে, ধরে নিই রেফারেন্সটি এখনও সেখানে বৈধ / শ্রগযোগ্য। এর আশেপাশে খালি চেষ্টা / ধরা দরকার?
ক্রিস মেরিসিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.