डमीज के लिए अपार्टमेंटस्टैट


120

मैंने इसे इस्तेमाल करते हुए बग को ठीक किया:

_Thread.SetApartmentState(ApartmentState.STA);

अब मैं यह समझना चाहता हूं कि इसका क्या मतलब है, और यह क्यों काम करता है!


1
यह पोस्ट आपकी मदद कर सकती है
आर्सेन मकर्त्चयन

जवाबों:


236

COM .NET का भव्य जनक है। इसके साथ उनके पास बहुत ही उदात्त लक्ष्य थे, जो उन चीजों में से एक है जो COM करता है लेकिन .NET पूरी तरह से एक वर्ग के लिए थ्रेडिंग गारंटी प्रदान कर रहा है। एक COM वर्ग प्रकाशित कर सकता है कि उसके पास किस प्रकार की थ्रेडिंग आवश्यकताएं हैं। और COM अवसंरचना सुनिश्चित करती है कि उन आवश्यकताओं को पूरा किया गया है।

यह पूरी तरह से .NET में अनुपस्थित है। आप कई थ्रेड्स में उदाहरण के लिए एक कतार <> ऑब्जेक्ट का उपयोग कर सकते हैं, लेकिन यदि आप ठीक से लॉक नहीं करते हैं, तो आपके पास अपने कोड में एक बुरा बग होगा जिसका निदान करना बहुत कठिन है।

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

एसटीए (सिंगल थ्रेडेड अपार्टमेंट) और एमटीए दो प्रकार के होते हैं। यह CoInitializeEx () कॉल में निर्दिष्ट है, एक फ़ंक्शन जिसे किसी भी थ्रेड द्वारा बुलाया जाना चाहिए जो COM के साथ कुछ भी करता है। जब भी यह थ्रेड शुरू होता है तो सीएलआर उस कॉल को स्वचालित रूप से करता है। आपके प्रोग्राम के मुख्य स्टार्टअप थ्रेड के लिए, यह आपके मुख्य () विधि पर [STAThread] या [MTAThread] विशेषता से पास होने का मान प्राप्त करता है। डिफ़ॉल्ट एमटीए है। थ्रेड्स के लिए जो आप स्वयं बनाते हैं वह आपके कॉल द्वारा SetApartmentState () में निर्धारित होता है। डिफ़ॉल्ट एमटीए है। थ्रेडपूल धागे हमेशा एमटीए होते हैं, जिन्हें बदला नहीं जा सकता।

विंडोज में बहुत सारे कोड होते हैं जिनके लिए STA की आवश्यकता होती है। आपके द्वारा उपयोग किए जाने वाले उल्लेखनीय उदाहरण क्लिपबोर्ड, ड्रैग + ड्रॉप और शेल डायलॉग (जैसे OpenFileDialog) हैं। और बहुत सारे कोड जो आप नहीं देख सकते हैं, जैसे यूआई स्वचालन कार्यक्रम और संदेशों को देखने के लिए हुक। उस कोड में से किसी को भी थ्रेड-सुरक्षित नहीं होना चाहिए, इसके लेखक को यह जानने में बहुत मुश्किल समय होता है कि बिना यह जाने कि इसे किस प्रोग्राम में उपयोग किया जाता है। तदनुसार, WPF या विंडोज फॉर्म प्रोजेक्ट का UI थ्रेड हमेशा ऐसे कोड को सपोर्ट करने के लिए STA होना चाहिए, जैसा कि कोई भी थ्रेड बनाता है जो एक विंडो बनाता है।

वादा आप कॉम के लिए सुनिश्चित करें कि आपका धागा है एसटीए तथापि करता आप एकल धागा फ्लैट अनुबंध का पालन करने की आवश्यकता है। वे बहुत कठोर हैं और जब आप अनुबंध को तोड़ते हैं, तो आप परेशानी का निदान करने के लिए मुश्किल हो सकते हैं। आवश्यकताएँ यह हैं कि आप कभी भी किसी भी समय के लिए थ्रेड को ब्लॉक नहीं करते हैं और आप एक संदेश लूप पंप करते हैं। बाद की आवश्यकता एक WPF या Winforms के UI थ्रेड द्वारा पूरी की जाती है, लेकिन यदि आप अपना स्वयं का STA थ्रेड बनाते हैं, तो आपको इसकी देखभाल स्वयं करने की आवश्यकता होगी। अनुबंध तोड़ने के लिए सामान्य निदान गतिरोध है।

इन आवश्यकताओं btw का समर्थन करने के लिए बिल्ट-इन CLR का काफी समर्थन है, जिससे आपको परेशानी से बाहर निकलने में मदद मिलेगी। ताला बयान और WaitOne () पद्धतियों संदेश पाश पंप जब यह एक जाँच धागे पर ब्लॉक। हालांकि यह केवल कभी-ब्लॉक आवश्यकता का ख्याल रखता है, फिर भी आपको अपना संदेश लूप बनाने की आवश्यकता है। WPR और Winforms दोनों में Application.Run ()।

मैंने पहले एक उत्तर दिया है जिसमें COM को खुश रखने के लिए एक संदेश लूप होने के महत्व के बारे में अधिक विवरण शामिल हैं। आपको यहां पोस्ट मिल जाएगी ।


4
बहुत बढ़िया जवाब! बग जो मैंने हल किया था, वह एक थ्रेड के लिए था जिसे मैंने एक लंबे समय तक चलने वाले रिपोर्ट बिल्डर के लिए बनाया था जो कि रिपोर्ट के कुछ हिस्सों को बनाने के लिए WPF नियंत्रणों का उपयोग करता था, ताकि समझ में आए, हालांकि मुझे इस बात की जानकारी नहीं है कि उस थ्रेड में एक संदेश लूप है ।
बेन्जोल

4
मुझे गंभीरता से इसे समझने के लिए कई बार MSDN पोस्ट को पढ़ना पड़ा, आपका उत्तर बहुत स्पष्ट और अच्छी तरह से लिखा गया है। धन्यवाद!
ak3nat0n
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.