2012-07-19 20 views
5

मैं बाहरी घटक का उपयोग कर रहा हूं जो समय-समय पर कार्यकर्ता थ्रेड से ईवेंट शूट करता है। मेरे ईवेंट हैंडलर में मैं मुख्य थ्रेड पर कुछ विधि का आह्वान करने के लिए एक डिस्पैचर का उपयोग करता हूं। यह अच्छी तरह से काम करता है ...डेडलॉक जब कार्यकर्ता धागा मुख्य धागे पर कुछ कहने का प्रयास करता है

private void HandleXYZ(object sender, EventArgs e) 
{ 
    ... 
    if(OnTrigger != null) 
     dispatcher.Invoke(OnTrigger, new TimeSpan(0, 0, 1), e); 
} 

हालांकि, जब कार्यक्रम बंद हो जाता है और बाहरी घटक निपटान() है, कार्यक्रम कभी कभी रुक जाता है (और केवल देखा है और कार्य प्रबंधक में मारा जा सकता है)।

जब मैं देख रहा हूं कि यह क्या हो रहा है ऐसा लगता है कि "घटक" मुख्य धागे पर लौटने की घटना का इंतजार कर रहा है (यह निपटान() विधि में रहता है), जबकि कार्यकर्ता थ्रेड प्रेषक के लिए आने का इंतजार कर रहा है मुख्य धागे के लिए उल्लिखित कॉल (यह प्रेषक में लटकती है। इन्वोक-लाइन)।

अभी के लिए मैंने Invoke में टाइमआउट जोड़कर शट डाउन समस्या हल की, जो काम करने लगता है लेकिन गलत लगता है। क्या ऐसा कुछ करने का क्लीनर तरीका है? क्या मैं मुख्य थ्रेड को बंद करने से पहले अन्य धागे से नौकरियों के लिए कुछ समय ले सकता हूं?

मैं "डिस्कनेक्ट" नीचे बंद से पहले घटना, की कोशिश की है, लेकिन वह मदद नहीं करता है, क्योंकि डिस्पैचर है (हो सकता है) पहले से ही इंतजार कर रहे हैं जब कार्यक्रम बंद करने के लिए शुरू करते हैं ...

पुनश्च: बाहरी घटक का अर्थ है कि मेरे पास स्रोत कोड तक पहुंच नहीं है ...

+0

पैराग्राफ का उपयोग करें अगली बार – Shai

+1

कोड पेस्ट करना एक बहुत – Vedran

उत्तर

6

हां, यह डेडलॉक का एक आम स्रोत है। यह लटकता है क्योंकि प्रेषक प्रेषक लूप से बाहर निकलता है, यह अब अनुरोध अनुरोधों का जवाब नहीं देगा। इसके बजाय BeginInvoke का उपयोग करने का एक त्वरित इलाज है, यह चालान लक्ष्य को निष्पादित करने के लिए इंतजार नहीं करता है। एक और quickie कार्यकर्ता थ्रेड की IsBackground संपत्ति को सही करने के लिए सेट है ताकि सीएलआर इसे मार डाले।

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

  • जब तक आप यकीन कि कार्यकर्ता धागा समाप्त और अब घटनाओं को बढ़ा सकते हैं कर रहे हैं बाहर निकलने के लिए मुख्य थ्रेड अनुमति नहीं देते: वहाँ दो "अच्छा" यह पूरी तरह से सुरक्षित रूप से करने के लिए तरीके हैं। This answer पैटर्न दिखाता है।

  • पर्यावरण के साथ बलपूर्वक प्रोग्राम को समाप्त करें। एक्सिट()।यह बहुत कच्चे लेकिन बहुत प्रभावी है, एक स्लेजहैमर आप केवल तब तक पहुंचेंगे जब आपके पास भारी थ्रेड प्रोग्राम होगा जहां यूआई थ्रेड केवल दूसरा नागरिक होगा। अजीब यह एक उपयुक्त दृष्टिकोण के रूप में ध्वनि हो सकता है, नए सी ++ भाषा मानक ने इसे एक प्रोग्राम को समाप्त करने के लिए एक समर्थित तरीके से बढ़ा दिया है। आप this answer में इसके बारे में अधिक पढ़ सकते हैं। ध्यान दें कि यह क्लीनअप फ़ंक्शंस को पंजीकृत करने की अनुमति देता है, आपको AppDomain.ProcessExit ईवेंट के साथ कुछ ऐसा करना होगा। ऐसा करने से पहले पहले बुलेट पर फ़ोकस करें।

+0

अच्छा जवाब! मैं कहूंगा कि BeginInvoke-way टाइमआउट से बेहतर लगता है। – FrankB

+0

क्या इसका मतलब यह है: यदि कार्यक्रम बंद नहीं हो रहा था, और मुख्य धागा घटना के लिए इंतजार करेगा ... क्या प्रेषक मुख्य धागे के माध्यम से आमंत्रित हो जाएगा, हालांकि मुख्य धागा "सक्रिय रूप से" इंतजार कर रहा है? – FrankB

+0

यह सुनिश्चित नहीं है कि यह मूल प्रश्न से कैसे संबंधित है। लेकिन मुख्य धागे में किसी भी तरह का "प्रतीक्षा" भी डेडलॉक का कारण बन सकता है। एक आमंत्रण() कॉल केवल तभी प्रेषित किया जा सकता है जब मुख्य धागा निष्क्रिय हो और प्रेषक लूप निष्पादित हो। –

1

घटना सदस्यता के लिए, वास्तव में उन्हें साफ करना एक अच्छा विचार है जब आप जानते हैं कि एक particluar ऑब्जेक्ट की आवश्यकता नहीं है। अन्यथा आप मेमोरी लीक बनाने का जोखिम उठाएंगे। आप weak event pattern (एमएसडीएन) पर भी एक नज़र डालना चाहते हैं।

अपने कोड को जानने के बिना, डेडलॉक के बारे में, हम केवल अनुमान लगा सकते हैं।

मुझे अपराधी के रूप में HandleXYZ() दिखाई नहीं देता है, तो मैं आपके IDisposable() implemntaion की जांच करूंगा। MSDN documentation पर एक नज़र डालें और इसे अपने कार्यान्वयन के साथ तुलना करें।

मुझे लगता है कि आपके कार्यान्वयन में कहीं भी कुछ विधि कॉल किए गए हैं जो GarbageCollector के समय पर निर्भर करते हैं, जो अनिश्चित है: कभी-कभी यह आपके मामले में काम कर सकता है, कभी-कभी ऐसा नहीं हो सकता है।

+0

धन्यवाद मदद मिलेगी ... लेकिन दुर्भाग्य से निपटान() के कोड (बाह्य घटक) – FrankB

+1

सवाल, @FrankB है मेरे पास उपलब्ध नहीं है, क्या आप कोई सफाई करते हैं? एक सामान्य नियम के रूप में, हमेशा किसी भी वर्ग को साफ़ करें जो 'IDispoeable()' लागू करता है। यदि वह तीसरा पक्ष घटक किसी चीज़ की प्रतीक्षा कर रहा है, तो यह मामला भी हो सकता है, कि आपका स्वयं का कोड कुछ संसाधनों को ठीक से रिलीज़ नहीं करता है। –

+0

वह अन्य घटक घटना को वापस करने की प्रतीक्षा करता है, जबकि मेरा इवेंट हैंडलर मुख्य थ्रेड के लिए प्रतीक्षा करता है (जो प्रतीक्षा घटक द्वारा अवरुद्ध है ...)। सफाई करना केवल समाधान है यदि मैं डिस्पैचर को मुख्य धागे की प्रतीक्षा करना बंद कर सकता हूं। क्या मैं टाइमआउट सेट करने के अलावा ऐसा कर सकता हूं? – FrankB

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