2010-09-25 12 views
19

मुझे पता है कि अगर मैं एक अलग थ्रेड से नियंत्रण में संशोधन कर रहा हूं, तो मुझे ध्यान रखना चाहिए क्योंकि WinForms और WPF नियंत्रण के राज्य को अन्य धागे से संशोधित करने की अनुमति नहीं देते हैं।केवल UI थ्रेड को यूआई को संशोधित करने की अनुमति क्यों है?

यह प्रतिबंध क्यों है?

यदि मैं थ्रेड-सुरक्षित कोड लिख सकता हूं, तो मुझे नियंत्रण स्थिति को सुरक्षित रूप से संशोधित करने में सक्षम होना चाहिए। तो यह प्रतिबंध क्यों मौजूद है?

+0

मेरा मानना ​​है कि इस प्रतिबंध में मौजूद कारणों में से एक कारण यह है कि विंडोज संदेश लूप को सुनने के लिए हमेशा एक और थ्रेड से कम गारंटी नहीं है। –

+1

@Tim: यह सही नहीं है, एकाधिक UI थ्रेड मौजूद हो सकते हैं, प्रत्येक के अपने संदेश लूप के साथ। उदाहरण के लिए, प्रगति पट्टी संवाद प्रदर्शित करने के लिए यह दूसरे थ्रेड को स्पिन करने की अनुमति है। –

+0

@बेन: इस पोस्ट को सी # के साथ टैग किया गया है। एक नेट अनुप्रयोग में, आपको ड्राइंग से संबंधित काम (या जोखिमपूर्ण व्यवहार या अपवाद जोखिम) करने के लिए हमेशा जीयूआई थ्रेड पर मार्शल नियंत्रण करना होगा। बेशक, यह आपको पृष्ठभूमि के काम करने के लिए किसी भी धागे को फैलाने से रोकता नहीं है। आने वाले वास्तविक Win32 संदेशों को सुनने के संबंध में, मुझे ऐसा करने का एकमात्र तरीका है (बाहरी कॉल के अलावा) "सुरक्षित ओवरराइड शून्य WNDProc (रेफ संदेश एम)" के साथ है। सिद्धांत रूप में, इस विधि को पारित संदेश ले सकते हैं और किसी भी धागे पर उनका उपयोग कर सकते हैं। –

उत्तर

19

कई जीयूआई ढांचे में यह सीमा है। Java Concurrency in Practice पुस्तक के अनुसार जटिल लॉकिंग से बचने का कारण है। समस्या यह है कि जीयूआई नियंत्रणों को यूआई, डेटा बाध्यकारी और आगे दोनों घटनाओं पर प्रतिक्रिया करनी पड़ सकती है, जिससे कई अलग-अलग स्रोतों से लॉक हो जाता है और इस प्रकार डेडलॉक्स का खतरा होता है। इस .NET WinForms (और अन्य UI) से बचने के लिए घटकों तक पहुंच को एक थ्रेड पर प्रतिबंधित कर दिया जाता है और इस प्रकार लॉकिंग से बचा जाता है।

+0

उसमें ActiveX नियंत्रणों (ब्रोवर कंट्रोल इत्यादि - संभवतः परोक्ष रूप से अप्रत्यक्ष रूप से Winforms एकीकरण के माध्यम से इंटरऑपरेबिलिटी) जोड़ें और आपके पास एक COM विरासत भी है जो सिंगल थ्रेडेड अपरेंटमेंट है। – TomTom

+1

विंडोज ** ** मालिक के धागे तक पहुंच प्रतिबंधित नहीं करता है। उस सीमा को .NET द्वारा पेश किया गया है। –

+0

@ बेन: मुझे यह नहीं पता था। मैं इसे प्रतिबिंबित करने के लिए अपना उत्तर अपडेट करूंगा। मैं जांचूंगा कि पुस्तक क्या कहती है। –

3

.NET को आपके नियंत्रण में पहुंचने का अधिकार सुरक्षित है जहां आपने इसे किसी भी समय बनाया था। इसलिए किसी अन्य धागे से आने वाली पहुंच कभी भी थ्रेड सुरक्षित नहीं हो सकती है।

8

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

1

आप अपना खुद का कोड थ्रेड-सुरक्षित बनाने में सक्षम हो सकते हैं, लेकिन आपके कोड में मौजूद लोगों के साथ मेल खाने वाले WinForm और WPF कोड में आवश्यक सिंक्रनाइज़ेशन प्राइमेटिव्स को इंजेक्ट करने का कोई तरीका नहीं है। याद रखें, दृश्यों के पीछे कई सारे संदेश पारित हो रहे हैं जो अंततः यूआई थ्रेड को नियंत्रण तक पहुंचने का कारण बनते हैं, बिना वास्तव में इसे महसूस करते हैं।

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

1

दरअसल, जहां तक ​​मुझे पता है, शुरुआत से ही योजना थी! किसी भी धागे से हर नियंत्रण का उपयोग किया जा सकता है! और सिर्फ इसलिए कि थ्रेड लॉकिंग की आवश्यकता थी जब किसी अन्य थ्रेड को नियंत्रण तक पहुंच की आवश्यकता होती थी - और क्योंकि लॉकिंग महंगा है - एक नया थ्रेडिंग मॉडल "थ्रेड किराए पर" कहा जाता है। उस मॉडल में, संबंधित नियंत्रण केवल एक धागे का उपयोग करके "संदर्भ" में एकत्रित किए जाएंगे, इस प्रकार आवश्यक लॉकिंग की मात्रा को कम किया जाएगा। बहुत अच्छा, हुह?

दुर्भाग्यवश, यह प्रयास सफल होने के लिए बहुत बोल्ड था (और थोड़ा और जटिल क्योंकि लॉकिंग अभी भी आवश्यक था), इसलिए पुराने पुराने विंडोज फॉर्म थ्रेडिंग मॉडल - एकल यूआई थ्रेड के साथ और स्वामित्व का दावा करने के लिए बनाने वाले थ्रेड के साथ नियंत्रण - हमारे जीवन को बनाने के लिए एक बार फिर डब्लूपीएफ में उपयोग किया जाता है ... आसान?

1

विंडोज कई परिचालनों का समर्थन करता है, जो विशेष रूप से संयोजन में उपयोग किए जाते हैं, स्वाभाविक रूप से थ्रेड-सुरक्षित नहीं हैं। क्या होना चाहिए, उदाहरण के लिए, यदि एक धागा 50 वें चरित्र से शुरू होने वाले टेक्स्ट फ़ील्ड में कुछ टेक्स्ट डालने का प्रयास कर रहा है, जबकि कोई अन्य थ्रेड उस फ़ील्ड के पहले 40 वर्णों को हटाने की कोशिश करता है? यह सुनिश्चित करने के लिए विंडोज़ लॉक का उपयोग करना संभव होगा कि दूसरा ऑपरेशन पहले तक पूरा नहीं हो सका, लेकिन ताले का उपयोग करके प्रत्येक ऑपरेशन में ओवरहेड जोड़ दिया जाएगा, और अगर किसी इकाई पर क्रियाओं की आवश्यकता होती है तो डेडलॉक की संभावना भी बढ़ेगी दूसरे का हेरफेर। एक विशेष खिड़की से जुड़ी कार्रवाइयों को एक विशेष थ्रेड पर होना आवश्यक है, एक साथ काम करने से असुरक्षित संयोजनों को रोकने के लिए आवश्यक होने की तुलना में अधिक कठोर आवश्यकता होती है, लेकिन यह विश्लेषण करना अपेक्षाकृत आसान है। कई धागे से नियंत्रण का उपयोग करना और कुछ अन्य माध्यमों के माध्यम से संघर्ष से परहेज करना आम तौर पर अधिक कठिन होगा।

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

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