2009-10-22 15 views
11

मैं बस एमएसडीएन पर events पर एक पृष्ठ पढ़ रहा था, और मैं उदाहरण कोड के एक स्निपेट में आया जो मुझे परेशान कर रहा है।प्रतिनिधियों की प्रतिलिपि

प्रश्न में कोड यह है:

// Make a temporary copy of the event to avoid possibility of 
// a race condition if the last subscriber unsubscribes 
// immediately after the null check and before the event is raised. 
EventHandler<CustomEventArgs> handler = RaiseCustomEvent; 

मैं कोड के इरादों को समझते हैं, लेकिन मैं यह देखने के लिए कि विशेष रूप से लाइन कुछ भी की एक प्रति बना रही है असफल। यह सब कर रहा है संदर्भ की प्रतिलिपि बना रहा है; यह वास्तव में प्रतिनिधि उदाहरण की गहरी प्रति नहीं बना रहा है। तो अंत में, यह वास्तव में दौड़ की स्थिति को बिल्कुल रोक नहीं देता है।

क्या मुझे यहां कुछ स्पष्ट याद आ रही है?

+1

उठाया जा सकता है वर्तमान विधि को इसे आग लगाने का मौका देने से पहले कस्टमवेन्ट को एक अलग थ्रेड पर शून्य पर सेट किया जा सकता है? –

उत्तर

17

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

+0

आह ठीक है कि बहुत अधिक समझ में आता है, धन्यवाद! मुझे कहना है, मैं इस बात से प्रभावित हूं कि इसका जवाब कितनी जल्दी हो गया! – David

4

आप सही हैं; यह संदर्भ की प्रतिलिपि बना रहा है।

हालांकि, प्रतिनिधि अपरिवर्तनीय हैं; जब आप किसी ईवेंट में हैंडलर जोड़ते हैं, तो एक नया प्रतिनिधि बनाया जाता है, जो मौजूदा हैंडलर को नए के साथ जोड़ता है, और उसके बाद फ़ील्ड को सौंपा जाता है।

क्षेत्र का संदर्भ देने वाला प्रतिनिधि उदाहरण बदल नहीं सकता है, इसलिए यह दौड़ की स्थिति से बचता है।

3

Eric Lippert पहले से ही इसे बहुत विस्तृत post में कवर किया गया है।

1

यह MSDN से भी है ..

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

0

if (whatever != null) whatever(); लगता है कि यह सुनिश्चित करता है कि whatever अशक्त जब whatever() कहा जाता है कभी नहीं है, लेकिन यह वास्तव में सुनिश्चित नहीं है कि एक पिरोया परिदृश्य में। एक अलग धागे की जांच और कॉल के बीच whatever = null सेट कर सकते हैं।

Foo temp = whatever; 
if (temp != null) temp(); 

यह कोड शून्य dereference की संभावना को हटा देता है, क्योंकि temp एक स्थानीय है और इसलिए इसे किसी भिन्न थ्रेड द्वारा कभी संशोधित नहीं किया जाएगा। इसलिए यह दौड़ की स्थिति को रोकता है। हालांकि यह सभी प्रासंगिक दौड़ स्थितियों को रोकता नहीं है। एरिक लिपर्ट ने more elaborate कुछ अन्य प्रो के बारे में चर्चा की कोड के साथ blems।

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