2010-06-05 19 views
5

मुझे अक्सर ऐसे कोड दिखाई देते हैं जो shown here है, यानी जहां ऑब्जेक्ट आवंटित किया जाता है और फिर "लॉक ऑब्जेक्ट" के रूप में उपयोग किया जाता है।किसी ऑब्जेक्ट पर लॉकिंग

ऐसा लगता है कि आप इस के लिए किसी ऑब्जेक्ट का उपयोग कर सकते हैं, जिसमें ईवेंट लॉक ऑब्जेक्ट भी शामिल है। एक नई वस्तु आवंटित क्यों करें जो कुछ भी नहीं करती? मेरी समझ यह है कि किसी ऑब्जेक्ट पर लॉक() को कॉल करना वास्तव में ऑब्जेक्ट को ही नहीं बदलता है, न ही यह वास्तव में इसे इस्तेमाल होने से रोकता है, इसे आसानी से एंकर पर एकाधिक लॉक स्टेटमेंट्स के प्लेसहोल्डर के रूप में उपयोग किया जाता है।

public class Shape : IDrawingObject, IShape 
{ 
    // Create an event for each interface event 
    event EventHandler PreDrawEvent; 
    event EventHandler PostDrawEvent; 

    object objectLock = new Object(); 

    // Explicit interface implementation required. 
    // Associate IDrawingObject's event with 
    // PreDrawEvent 
    event EventHandler IDrawingObject.OnDraw 
    { 
     add 
     { 
      lock (objectLock) 
      { 
       PreDrawEvent += value; 
      } 
     } 
     remove 
     { 
      lock (objectLock) 
      { 
       PreDrawEvent -= value; 
      } 
     } 
    } 
} 

तो मेरे सवाल है, यह वास्तव में क्या करने के लिए एक अच्छी बात है?

+0

(अद्यतन देखें, बीटीडब्ल्यू) –

उत्तर

7
घटना ही

नहीं, आप ऐसा नहीं कर सकते सहित

। एक "घटना" वास्तव में केवल कुछ एक्सेसर विधियों है। मान लें कि आप समर्थन प्रतिनिधि का मतलब है, यह बहुत बुरा होगा - प्रतिनिधि अपरिवर्तनीय हैं: हर बार जब आप एक ग्राहक को जोड़ते/हटाते हैं, तो आपको अलग प्रतिनिधि मिलता है।

असल में, 4.0 कंपाइलर अब Interlocked का उपयोग कर लॉक-फ्री कोड के साथ ऐसा करता है - इसके बजाय इस दृष्टिकोण का पालन करने योग्य हो सकता है।

अपने उदाहरण में, objectLock सुनिश्चित करता है कि सभी कॉलर्स (कि उदाहरण के लिए) ही वस्तु है, जो महत्वपूर्ण है के खिलाफ ताला लगा रहे हैं - this पर ताला लगा (जो की कुरूपता कैसे सी # संकलक इस्तेमाल किया बिना लेकिन काम करने के लिए)।

-

अद्यतन: अपने उदाहरण से पता चलता कोड से पहले सी # 4.0 आवश्यक है कि, एक क्षेत्र की तरह घटना अंदर प्रकार क्षेत्र के लिए सीधे बात करने के लिए उपयोग: सामान्य क्षेत्र की तरह घटना ताला लगा सम्मान नहीं किया गया था। यह सी # 4.0 में बदल दिया गया था; अब आप (सी # 4.0 में) सुरक्षित रूप से फिर से लिख सकते हैं इस रूप में:

public class Shape : IDrawingObject, IShape 
{ 
    // Create an event for each interface event 
    event EventHandler PreDrawEvent; 
    event EventHandler PostDrawEvent; 

    event EventHandler IDrawingObject.OnDraw 
    { 
     add { PreDrawEvent += value; } 
     remove { PreDrawEvent -= value; } 
    } 
} 

सभी सही व्यवहार तो पीछा किया जाता है।

+0

तो आप कह रहे हैं कि अगर लॉक (प्रीड्राइवेंट) परिणामस्वरूप हर बार प्रतिनिधि को बदल दिया गया तो एक अलग ऑब्जेक्ट लॉक हो जाएगा? उह .. यह बहुत प्रतीत नहीं होता .. सहज ज्ञान युक्त। मैंने हमेशा यह माना है कि घटनाएं कंटेनर थीं, कुछ हद तक सूची <> जिसमें प्रतिनिधि शामिल थे .. क्या यह गलत धारणा है? –

+0

@ माइस्टेर मैन - बदतर: एक सदस्यता रद्द की गई घटना 'शून्य' है, इसलिए यह पूरी तरह विफल हो जाएगी। आपकी धारणा गलत है। –

+1

लॉकिंग की बात आने पर धारणाएं बनाना वास्तव में एक बुरा विचार है। यह जानकर कि लॉक काम कैसे सर्वोपरि है। – Rusty

1

यह एक निजी स्थैतिक क्षेत्र को लॉक करने की अनुशंसा की जाती है क्योंकि यह सुनिश्चित करता है कि समानांतर में लॉक तक पहुंचने का प्रयास करने वाले एकाधिक थ्रेड अवरुद्ध किए जाएंगे। कक्षा के उदाहरण (lock(this)) या कुछ उदाहरण फ़ील्ड को लॉक करना समस्याग्रस्त हो सकता है क्योंकि यदि दो धागे ऑब्जेक्ट के दो अलग-अलग उदाहरणों पर विधि को कॉल करते हैं तो वे एक साथ लॉक स्टेटमेंट दर्ज कर पाएंगे।

+0

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

+0

वही बात: 'इस' या 'आवृत्ति फ़ील्ड' पर लॉक करना खराब हो सकता है क्योंकि ऑब्जेक्ट फ़ील्ड ऑब्जेक्ट के उदाहरण के आधार पर बदल जाएगा जबकि स्थिर रीडोनली फ़ील्ड कभी नहीं बदलेगा। –

+0

मैं वास्तव में नहीं देखता कि समस्या क्या है। संपूर्ण बिंदु एक चर के एक उदाहरण को लॉक करना है ताकि एकाधिक धागे उस उदाहरण को बदल नहीं सकें। आप दो अलग-अलग उदाहरणों को एक साथ संशोधित होने से क्यों रोकना चाहेंगे? –

2

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

निजी नौकरी करने वाले निजी सदस्यों का उपयोग करना कुछ ऐसा नहीं है जो अच्छी तरह से स्केल करता है। यदि आपको पता चलता है कि आपको रीफैक्टरिंग या डिबगिंग के दौरान कोड के किसी अन्य क्षेत्र को लॉक करने की आवश्यकता है, तो आपको एक और निजी सदस्य ढूंढना होगा। जहां चीजें तेजी से खट्टा हो सकती हैं: आप उसी निजी सदस्य को फिर से चुन सकते हैं। दरवाजे पर दस्तक डेडलॉक।

ऐसा नहीं होता है यदि आप लॉक ऑब्जेक्ट को साझा चर के विशिष्ट सेट पर समर्पित करते हैं जिसे संरक्षित करने की आवश्यकता होती है। आपको इसे एक अच्छा नाम भी देने की अनुमति देता है।

+0

यही कारण है कि मैं घटना का उपयोग करने का सुझाव दिया, क्योंकि वह "ऑब्जेक्ट" था जिसे आप जोड़ रहे थे। हालांकि, अगर मैं मार्क की टिप्पणियों को सही ढंग से समझ रहा हूं, तो लॉकिंग ऑब्जेक्ट के रूप में एक ईवेंट का उपयोग करना बहुत बुरी चीज है ... –

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