2016-12-02 12 views
6

एक पुन: प्रयोज्य कस्टम फ़ंक्शन लिखने पर विचार करें जो उसके शरीर के अंदर COM ऑब्जेक्ट बनाता है और कुछ COM इंटरफेस को कॉल करता है। इसके लिए ठीक से काम करने के लिए, CoInitializeEx और मिलान CoUninitialize एपीआई को कॉल किया जाना चाहिए।कॉम प्रारंभिकरण और सफाई-कार्य ग्रैन्युलरिटी पर उपयुक्त सफाई?

उन COM प्रारंभिकरण और सफाई एपीआई को के अंदर कॉल करना फ़ंक्शन का बॉडी कॉलर को COM कार्यान्वयन विवरण छुपाएगा, और कॉलर से भी बोझ हटा देगा।

लेकिन CoInitializeEx पर कॉल कर रहा है और फ़ंक्शन के शरीर के अंदर CoUninitialize मिलान करने के लिए एक अच्छा कोडिंग अभ्यास माना जाता है?

फ़ंक्शन-ग्रैन्युलरिटी स्तर पर उन COM init/cleanup फ़ंक्शंस को कॉल करना प्रत्येक फ़ंक्शन कॉल के लिए बहुत अधिक ओवरहेड इंगित करेगा?

क्या इस डिज़ाइन में अन्य कमीएं हैं?

+0

"* दोष * *" ऐसे कार्यों की नेस्टेड या रिकर्सिव कॉल अभी भी संभव हो सकती है? – alk

+0

@alk - हाँ, इस फ़ंक्शन को रिकर्सिव – RbMm

+0

कहा जा सकता है मुझे लगता है कि यह केवल एक सी/सी ++ विशिष्ट प्रश्न नहीं है। – alk

उत्तर

6

यह भयानक अभ्यास और मौलिक रूप से गलत है। एक बड़ा सौदा क्या मायने रखता है दूसरा तर्क (dwCoInit) के लिए मूल्य। यह COINIT_APARTMENTTHREADED होना चाहिए, जिसे अक्सर एसटीए, या COINIT_MULTITHREADED (MTA) के लिए संक्षिप्त किया जाता है। यह वादा है जो आप बनाते हैं, दिल-आशा-से-मरने वाली शैली को पार करते हैं। यदि आप वादा तोड़ते हैं तो कार्यक्रम मर जाएगा। आमतौर पर डेडलॉकिंग द्वारा, अपेक्षित घटनाएं नहीं मिल रही हैं या अस्वीकार्य धीमी गति से पीड़ित हैं।

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

जब आप एमटीए का चयन करते हैं तो आप किसी भी समर्थन का वादा नहीं करते हैं। घटक को खुद को थ्रेड-सुरक्षित रखने के लिए खुद को रोकना चाहिए। अक्सर घटक को सुरक्षित घर देने के लिए COM बुनियादी ढांचे को स्वयं धागा बनाकर स्वचालित रूप से किया जाता है। एक और विस्तार जो आपको देखभाल करने की आवश्यकता है इंटरफ़ेस पॉइंटर को मार्शल करना है, को CoararshalInterThreadInterfaceInStream() सहायक फ़ंक्शन या अधिक सुविधाजनक IGlobalInterfaceTable इंटरफ़ेस की आवश्यकता है। यह सुनिश्चित करता है कि प्रॉक्सी बनाई गई है जो आवश्यक थ्रेड संदर्भ स्विच का ख्याल रखती है।

एमटीए सुविधाजनक लगता है, लेकिन बिना किसी परिणाम के, एक साधारण संपत्ति गेटर कॉल जितना अधिक x10000 अधिक समय ले सकता है। थ्रेड संदर्भ स्विच द्वारा लगाए गए ओवरहेड और स्टैक फ्रेम में किसी भी तर्क और वापसी मूल्य की प्रतिलिपि बनाने की आवश्यकता। और इंटरफ़ेस पॉइंटर को मार्शल करना आसानी से विफल हो सकता है, COM घटकों के लेखक अक्सर आवश्यक प्रॉक्सी/स्टब प्रदान नहीं करते हैं या वे जानबूझकर इसे छोड़ देते हैं क्योंकि डेटा को कॉपी करने के लिए यह बहुत मुश्किल या महंगा है।

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

पसंद को उस कोड द्वारा बनाया जाना चाहिए जो धागे को बनाया और प्रारंभ किया गया है, हमेशा ऐप स्वयं। जब तक पुस्तकालय कॉल को सुरक्षित करने के उद्देश्य से धागा नहीं बनाता है। लेकिन फिर कोड के परिणाम हमेशा धीमा होने के साथ। आप अपनी लाइब्रेरी के कॉलर को याद दिलाते हैं कि उसे अपरिहार्य CO_E_NOTINITIALIZED त्रुटि कोड लौटकर सही नहीं मिला।

Fwiw, यह कुछ है जो आप .NET Framework में वापस देखते हैं। किसी भी प्रबंधित कोड को निष्पादित करने से पहले सीएलआर हमेशा CoInitializeEx() को कॉल करता है। अभी भी एक विकल्प जो ऐप के प्रोग्रामर द्वारा किया जाना चाहिए, या अधिक आम तौर पर परियोजना टेम्पलेट, मुख्य() या थ्रेड.SetApartmentState() पर [STAThread] विशेषता के साथ किया गया है, जो एक कार्यकर्ता थ्रेड के लिए कॉल करता है।

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