2013-08-29 6 views
5

मैं ऐसे एप्लिकेशन का उपयोग कर रहा हूं जो मैन्युअल रीसेट इवेंट का उपयोग करके थ्रेड सिंक्रनाइज़ करता है। FxCop ने मुझे उन वस्तुओं का निपटान करने के लिए कहा। मैं निम्नलिखित चर्चा जो मुझे एक ही बताया पाया:मैन्युअल रीसेट इवेंट का निपटान कब किया जाना चाहिए?

Do I need to Dispose() or Close() an EventWaitHandle?

लेकिन मैं नहीं जानता कि जब एक ManualResetEvent का एक उदाहरण निपटान के लिए।

private void btn_Click(object sender, EventArgs e) 
{ 
    var mre = new ManualResetEvent(false); 
    new Thread(() => this.SetEvent(mre)).Start(); 
    for (int i = 0; i < 10; ++i) 
    { 
     new Thread(() => this.WaitFor(mre)).Start(); 
    } 
} 

private void SetEvent(ManualResetEvent manualResetEvent) 
{ 
    Thread.Sleep(10000); 
    manualResetEvent.Set(); 
} 

private void WaitFor(ManualResetEvent manualResetEvent) 
{ 
    manualResetEvent.WaitOne(); 
} 

समस्या यह है कि ManualResetEvent के कई उदाहरण मौजूद हैं और एक से अधिक थ्रेड प्रत्येक उदाहरण के लिए इंतजार कर रहे हैं है:

निम्नलिखित सरल कोड समस्या को दर्शाता है।

अगर मैं एक सूची में उदाहरणों को याद मैं जब यह निपटान के लिए पता नहीं है। WaitOne() के बाद इसे डिस्पोज़ करना - कॉल इसे कई बार निपटान करेगा और शायद इसे डिस्पोजेड किया जाएगा जबकि अन्य थ्रेड अभी भी प्रतीक्षा कर रहे हैं।

धागा है कि घटना बनाया यह करने के लिए किसी भी संदर्भ नहीं है। सेटर-थ्रेड को इसका निपटान नहीं करना चाहिए क्योंकि इस एमआरई के लिए अन्य धागे इंतजार कर रहे हैं। जैसा कि पहले उल्लेख किया गया है, प्रत्येक प्रतीक्षा धागा इसे निपटाने में सक्षम नहीं है।

तो सवाल यह है: जब इस ManualResetEvent निपटारा किया जाना चाहिए?

+1

कोड गैरकानूनी है और एमआरई का केवल * एक * उदाहरण है। विधि के अंत में इसे निपटाना ठीक है। –

+1

नहीं, मुझे ऐसा नहीं लगता है।कोड जो एमआरई बनाता है वह एक बटन क्लिक इवेंट हैंडलर है। आप इसे कई बार क्लिक करने में सक्षम हैं जो एकाधिक एमआरई बनाता है। उपरोक्त कोड सरलीकृत है। इस विधि के अंत में एमआरई का निपटारा काम नहीं करेगा क्योंकि विधि समाप्त होने के बाद 11 एमआरई का उपयोग कर रहे हैं। सेटर-थ्रेड 10 सेकंड तक प्रतीक्षा करता है और 10 अन्य धागे इस एमआरई के लिए इंतजार कर रहे हैं। –

उत्तर

5

ManualResetEvent निपटारा किया जाना चाहिए जब आप इसकी ज़रूरत नहीं है। आपका असली सवाल यह है, "मुझे कैसे पता चलेगा कि अब मुझे इसकी आवश्यकता नहीं है?" जब धागे से किया जाता है

आमतौर पर कुछ अधिसूचित किया गया है, और आप धागे पर Join कहते हैं। या थ्रेड यह इंगित करने के लिए कुछ घटना सेट करता है कि यह समाप्त हो गया है। यदि आपके पास एकाधिक धागे हैं, तो वे सभी CountdownEvent सिग्नल कर सकते हैं। थ्रेड अधिसूचना को प्रबंधित करने के कई अन्य तरीके हैं।

मुद्दा यह है कि यह आप पर निर्भर है कि वे सही ढंग से निपटारा कर रहे हैं बनाने के लिए आप संसाधनों के आवंटन कर रहे हैं है। उपर्युक्त आपके कोड में, आपके पास ट्रैक रखने का कोई तरीका नहीं है कि कौन से धागे निष्पादित हो रहे हैं या कौन से धागे जुड़े हैं ManualResetEvent। यदि आप यह सुनिश्चित करना चाहते हैं कि एमआरई का सही तरीके से निपटान किया गया है, तो आपको इसे ट्रैक करना होगा, न केवल एमआरई का ट्रैक रखें बल्कि यह भी थ्रेड इसका उपयोग कर रहे हैं, जो थ्रेडों ने अपना काम पूरा कर लिया है, और जब सभी को सूचित किया जाता है धागे किए जाते हैं ताकि आप चीजों का निपटान कर सकें।

आपकी विशेष स्थिति में, यदि आपको वास्तव में एमआरई का उपयोग करना है, तो संभवतः मैं डेटा संरचना तैयार करता हूं जिसमें धागे और एमआरई के संदर्भ होते हैं, और CountdownEvent कि थ्रेड सिग्नल होने पर संकेत मिलता है। की तरह कुछ:

class WorkUnit 
{ 
    public List<Thread> Threads; 
    public ManualResetEvent MRE; 
    public CountdownEvent CE; 
} 

अब, जब एक धागा खत्म यह इस करता है:

workUnit.CE.Signal(); 

अपने कार्यक्रम (शायद मुख्य थ्रेड) के किसी अन्य भाग समय-समय पर काम इकाइयों की सूची की जाँच करता है। उस सूची में प्रत्येक आइटम के लिए यह यह करता है:

if (workUnit.CE.WaitOne(0)) 
{ 
    foreach (Thread t in workUnit.Threads) 
    { 
     t.Join(); 
    } 
    // dispose the MRE and the CE 
    // and remove the work unit from the list 
} 

हां, यह बहुत काम है। यह संभवतः सबसे अच्छा है यदि आप अपने प्रोग्राम को ढांचा बना सकते हैं ताकि आपको इस तरह की चीज न करें।

+0

धन्यवाद जिम। एकमात्र समस्या यह है कि मुझे नहीं पता कि एमआरई के लिए कितने धागे इंतजार करेंगे और यही कारण है कि मैं एक काउंटरडाउनएवेंट शुरू नहीं कर सकता। लेकिन आप सही हैं कि मुझे एक ऐसे डिज़ाइन पर विचार करना चाहिए जो जानता है कि एमआरई की अब आवश्यकता नहीं है। वर्तमान में कार्यकर्ता थ्रेड के अंत के लिए कोई धागा इंतजार नहीं कर रहा है क्योंकि वे कुछ मानों की गणना करते हैं और परिणाम को नियंत्रण में प्रदर्शित करते हैं। उसके बाद कार्य (ओह हाँ मैं धागे के बजाय कार्यों का उपयोग कर रहा हूं लेकिन मुझे लगता है कि समस्या अभी भी वही है क्योंकि एक कार्य काउंटरडाउनइवेंट को जारी रख सकता है) समाप्त होता है और वहां कोई कोड नहीं है जो स्पष्ट रूप से प्रतीक्षा करता है। –

+0

मुझे अपने मामलों के लिए एक समाधान मिला। सेटर-थ्रेड बनाया गया है और केवल एक विधि में शुरू किया गया है जो एमआरई देता है। इस विधि के कॉलर एमआरई के बारे में जानता है और इसे कई धागे में प्रचारित करता है लेकिन यह रिसीवर के बारे में जानता है। मैं एमआरई को एक हैंडलर ऑब्जेक्ट में लपेटने में सक्षम हूं जो एमआरई रिसीवर का प्रबंधन करता है और वहां समाप्त होने की प्रतीक्षा करता है। उसके बाद एमआरई जारी किया जा सकता है। आपकी सहायता के लिए धन्यवाद. –

संबंधित मुद्दे