WinForms में, आप अन्य धागे से यूआई नियंत्रण क्यों अपडेट नहीं कर सकते?

मुझे यकीन है कि इसके लिए एक अच्छा (या कम से कम सभ्य) कारण है। यह क्या है?

0
ro fr bn

8 उत्तर

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

संपादित करें:

अन्य भाषाओं में जैसे कि सी ++ आप हैं   कोशिश करने और इसे करने के लिए स्वतंत्र (बिना एक   अपवाद के रूप में फेंक दिया जा रहा है   WinForms), लेकिन आप सीखने खत्म हो जाएगा   कठिन तरीका!

आह हाँ ... मैं सी/सी ++ और सी # के बीच स्विच करता हूं और इसलिए थोड़ा और सामान्य था तो मुझे होना चाहिए था, क्षमा करें ... वह सही है, आप इसे </> कर सकते हैं सी/सी ++ में ऐसा करते हैं , लेकिन यह आपको काटने के लिए वापस आ जाएगा!

0
जोड़ा

मुझे लगता है कि यह एक शानदार सवाल है - और मुझे लगता है कि बेहतर जवाब की आवश्यकता है।

निश्चित रूप से एकमात्र कारण यह है कि कहीं ढांचे में कुछ ऐसा है जो बहुत धागा-सुरक्षित नहीं है। क्या यह .NET या Win32 के साथ एक समस्या है - और मेरे लिए क्या करने के बजाय स्रोत को ठीक करने के लिए कोई धक्का नहीं है, मेरे लिए, एक बुरा काम की तरह लगता है?

कोई भी जानता है कि वास्तविक अंतर्निहित मुद्दा कहां है?

0
जोड़ा

क्योंकि आप आसानी से डेडलॉक (अन्य मुद्दों के बीच) के साथ समाप्त हो सकते हैं।

Exmaple के लिए, आपका माध्यमिक धागा यूआई नियंत्रण को अद्यतन करने का प्रयास कर रहा है, लेकिन यूआई नियंत्रण द्वितीयक थ्रेड द्वारा लॉक किए गए संसाधन के लिए इंतजार कर रहा है, इसलिए दोनों धागे एक दूसरे के लिए इंतजार कर रहे हैं। जैसा कि अन्य ने टिप्पणी की है कि यह स्थिति यूआई कोड के लिए अद्वितीय नहीं है, लेकिन यह विशेष रूप से आम है।

सी ++ जैसी अन्य भाषाओं में आप कोशिश करने और ऐसा करने के लिए स्वतंत्र हैं (बिना किसी अपवाद के WinForms के रूप में फेंक दिया जा सकता है), लेकिन आपका एप्लिकेशन फ्रीज हो सकता है और प्रतिक्रिया देना बंद कर देना चाहिए।

संयोग से, आप यूआई थ्रेड को आसानी से बता सकते हैं कि आप एक नियंत्रण को अपडेट करना चाहते हैं, बस एक प्रतिनिधि बनाएं, फिर उस प्रतिनिधि पर (एसिंक्रोनस) BeginInvoke विधि को अपने प्रतिनिधि को पास कर दें। जैसे

myControl.BeginInvoke(myControl.UpdateFunction);

यह एक कार्यकर्ता थ्रेड से सी ++/एमएफसी पोस्टमेसेज करने के बराबर है

0
जोड़ा
-1: लॉक संसाधनों की प्रतीक्षा समस्या नहीं है। समस्या दौड़ की स्थिति है, जो कि किसी भी कोड में बड़ी मात्रा में मौजूद है जिसे बहु-थ्रेडेड वातावरण में उपयोग करने के लिए डिज़ाइन नहीं किया गया था। आप इसे चेकफोर इलगैलल क्रॉस थ्रेडकॉल झूठी करने के लिए, और कुछ मजाकिया होने तक डेडलॉक-मुक्त ऑपरेशन का निरीक्षण करें।
जोड़ा लेखक Roman Starkov, स्रोत
मुझे यकीन नहीं है कि यह जवाब क्यों स्वीकार किया गया था। यह बस सही जवाब नहीं है। जब भी आपके पास एकाधिक धागे होते हैं तो डेडलॉक्स हो सकते हैं। जीयूआई कार्यक्रमों में निहित कुछ भी नहीं है जो उन्हें होने की अधिक संभावना बनाता है। इसके अलावा, अगर आप BeginInvoke() का उपयोग करते हैं तो भी वे आसानी से हो सकते हैं। ब्रायन एनसिंक का जवाब सही है।
जोड़ा लेखक mhenry1384, स्रोत

1.0/1.1 में वापस डिबगिंग के दौरान कोई अपवाद नहीं डाला गया था, इसके बजाय आपको जो मिला वह एक अंतराल रन-टाइम फांसी परिदृश्य था। अच्छा! :) इसलिए 2.0 के साथ उन्होंने इस परिदृश्य को अपवाद फेंक दिया और काफी हद तक ऐसा किया।

इसके लिए वास्तविक कारण शायद (एडम हैइल राज्यों के रूप में) कुछ प्रकार की समवर्ती/ताली समस्या है। ध्यान दें कि सामान्य .NET एपीआई (जैसे TextBox.Text = "हैलो";) आदेश भेजता है (जिसके लिए तत्काल कार्रवाई की आवश्यकता होती है) जो अपडेट को क्रियान्वित करने वाले से अलग थ्रेड पर किए गए मुद्दों को बना सकता है। Invoke/BeginInvoke का उपयोग करके POST का उपयोग करता है जो कार्रवाई को कतार देता है।

SEND और POST यहां पर अधिक जानकारी।

0
जोड़ा

अद्यतन कार्यों के भीतर सिंक्रनाइज़ेशन को लागू करने की आवश्यकता भी होगी जो एक साथ बुलाए जाने के प्रति संवेदनशील हैं। यूआई तत्वों के लिए ऐसा करना दोनों अनुप्रयोगों और ओएस स्तरों पर महंगा होगा, और कोड के विशाल बहुमत के लिए पूरी तरह से अनावश्यक होगा।

कुछ एपीआई सिस्टम के मौजूदा थ्रेड स्वामित्व को बदलने का एक तरीका प्रदान करते हैं ताकि आप अस्थायी रूप से (या स्थायी रूप से) अन्य धागे से सिस्टम को इंटर-थ्रेड संचार का उपयोग किए बिना अद्यतन कर सकें।

0
जोड़ा

मुझे लगता है कि यह एक शानदार सवाल है -   और मुझे लगता है कि बेहतर की जरूरत है   इस सवाल का जवाब।

     

निश्चित रूप से वहां एकमात्र कारण है   कहीं ढांचे में कुछ है   यह बहुत धागा-सुरक्षित नहीं है।

सिस्टम "Windows.Forms में प्रत्येक नियंत्रण पर" कुछ "लगभग हर एक उदाहरण सदस्य है।

The MSDN documentation for many controls in System.Windows.Forms, if not all of them, say "Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe."

इसका मतलब है कि उदाहरण कोड जैसे TextBox.Text {get; सेट;} पुनर्वित्त नहीं हैं।

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

[संपादित करें]

यद्यपि यह प्रश्न केवल "क्यों" पूछता है, यह एक लेख का एक लिंक है जो बताता है कि "कैसे":

How to: Make Thread-Safe Calls to Windows Forms Controls on MSDN

http://msdn.microsoft.com/en-us/library/ms171728.aspx

0
जोड़ा
पुनर्विक्रेता होना पूरी तरह से संभव है लेकिन थ्रेड-सुरक्षित नहीं है। विचार करें (एफ) => {x + = 1; f (x); एक्स - = 1; } जो अतिप्रवाह के लिए ठीक है अगर एफ (एक्स) एक धागे पर लैम्ब्डा को फिर से प्रस्तुत करता है लेकिन बहु-प्रसारित होने पर एक्स पर दौड़ता है।
जोड़ा लेखक Jeffrey Hantin, स्रोत

हम्म मुझे पूरा यकीन नहीं है लेकिन मुझे लगता है कि जब हमारे पास प्रतीक्षा सलाखों जैसे प्रगति नियंत्रण होते हैं, प्रगति सलाखों को हम अपने मूल्यों को किसी अन्य धागे से अपडेट कर सकते हैं और सब कुछ बिना किसी ग्लिच के काम करता है।

0
जोड़ा

हालांकि यह उचित लगता है कि जॉन्स का जवाब सही नहीं है। वास्तव में जब भी Invoke का उपयोग करते हैं तब भी आप सुरक्षित नहीं हैं मृत-लॉक परिस्थितियों में नहीं चल रहे हैं। इनवॉक का उपयोग करके पृष्ठभूमि थ्रेड पर निकाली गई घटनाओं से निपटने पर भी इस समस्या का कारण बन सकता है।


असली कारण रेस की स्थिति के साथ और अधिक करना है और प्राचीन Win32 बार में वापस देता है। मैं यहां विवरणों की व्याख्या नहीं कर सकता, कीवर्ड संदेश पंप, WM_PAINT ईवेंट और "SEND" और "POST" के बीच सूक्ष्म अंतर हैं।


अधिक जानकारी यहां यहां और यहां

0
जोड़ा