2011-06-15 16 views
6

मैंने .NET 4.0 में विशेष रूप से संभावित बहु-थ्रेडेड परिदृश्यों में एक नई प्रवृत्ति देखी है, जो घटनाओं से परहेज कर रहा है, और इसके बजाय ग्राहक विधियां प्रदान कर रहा है।सब्सक्राइबर विधि बनाम घटना

उदाहरण के लिए, System.Threading.Tasks.Task और Task<TResult> में पूर्ण या समाप्त घटना के बजाय ContinueWith() विधियां हैं। एक और उदाहरण System.Threading.CancellationToken है: इसमें Register() विधि रद्द करने की आवश्यकता के बजाय विधि है।

जबकि Task.ContinueWith() तार्किक है, क्योंकि यह (घटनाओं के साथ इतना सुंदर नहीं होगा) आसान काम श्रृंखलन के लिए अनुमति देता है, और यह भी (क्योंकि इस तरह से, Task<TResult> उचित भार के प्रदान कर सकते हैं Task<TResult>Task से विरासत के लिए अनुमति देता है कि, जो किसी ईवेंट के लिए संभव नहीं होगा: यदि आपके पास कोई ईवेंट इवेंट हैडलर कार्य में समाप्त हुआ है, तो आप अन्य ईवेंट बना सकते हैं, कहें, ईवेंट EventHandler<TaskResultEventArgs>Task<TResult> में समाप्त हुआ, जो बहुत अच्छा नहीं है), लेकिन मुझे नहीं मिल रहा है रद्दीकरण टोकन के लिए एक ही स्पष्टीकरण। रजिस्ट्रार()।

तो, इसी तरह के परिदृश्यों में घटनाओं के नुकसान क्या हैं? क्या मुझे इस पैटर्न का भी पालन करना चाहिए? स्पष्टीकरण के लिए, नीचे दिए गए में से कौन सा मुझे चुनना चाहिए? मुझे दूसरे के खिलाफ कब पसंद करना चाहिए?

public event EventHandler Finished; 

// or 

public IDisposable OnFinished(Action continuation) 

बहुत बहुत धन्यवाद!

+0

@ जोन स्कीट: धन्यवाद, मैंने यह नहीं देखा कि मेरे परी ब्रैकेट को कुछ भागने की आवश्यकता है। – ShdNx

+0

यूआई इवेंट इत्यादि को यूआई संदेश कतार का उपयोग करके पोस्ट किया जा सकता है और संभावित रूप से एक प्रतिनिधि या साधारण कार्य का उपयोग करने की तुलना में वास्तव में धीमी/भारी हो सकती है .. – CodingBarfield

+0

@ बरफील्डएमवी: एक्शन कॉल को उसी तकनीक का उपयोग करके पोस्ट किया जा सकता है जिसमें Invoke/BeginInvoke के साथ यूआई धागा यह अंतर नहीं है। –

उत्तर

2

मुझे लगता है कि ग्राहक विधियों का उपयोग करने का एक फायदा यह है कि आपके पास उस प्रतिनिधि को आसानी से निर्दिष्ट करने की क्षमता है जिसे आपके प्रतिनिधि को निष्पादित किया जाएगा। रद्द करने के लिए this overload देखें। रजिस्ट्रार()।

अद्यतन: ठीक है, वास्तव में आप सिंक्रनाइज़ेशन संदर्भ निर्दिष्ट कर सकते हैं जो आपके प्रतिनिधि को पोस्ट किया जाएगा।

आप प्रवृत्ति के बारे में सही हैं।

नए घटकों घटना-आधारित अतुल्यकालिक पैटर्न का उपयोग नहीं करना चाहिए: MSDN पत्रिका में This article निम्नलिखित कहा गया। दृश्य स्टूडियो अतुल्यकालिक समुदाय टैक्नोलॉजी प्रीव्यू (CTP) एक दस्तावेज़ कार्य-आधारित अतुल्यकालिक पैटर्न का वर्णन है, जिसमें घटकों टास्क लौट सकते हैं और टास्क बजाय SynchronizationContext के माध्यम से घटनाओं को ऊपर उठाने की वस्तुओं में शामिल हैं। कार्य-आधारित एपीआई एनईटी में एसिंक्रोनस प्रोग्रामिंग का भविष्य हैं।

और document लेख को संदर्भित करता है कहते हैं

दीक्षा और नल में एक अतुल्यकालिक आपरेशन के पूरा होने एक भी विधि का प्रतिनिधित्व करती हैं, और इस प्रकार वहाँ केवल एक ही नाम के लिए तरीका है। यह IAsyncResult पैटर्न, या एपीएम पैटर्न, जहां BeginMethodName और EndMethodName तरीकों के लिए आवश्यक हैं, और घटना आधारित अतुल्यकालिक पैटर्न, या EAP, जहां एक MethodNameAsync अलावा आवश्यक है के विपरीत के विपरीत है एक या अधिक घटनाओं के लिए, घटना हैंडलर प्रतिनिधि प्रकार, और EventArg- व्युत्पन्न प्रकार।

और वास्तव में, कई लोगों की बजाय एक चीज़ का ख्याल रखना अच्छा है। लेकिन यह ईएपी पर टीएपी का अधिक लाभ है, न कि ग्राहक तरीकों का लाभ।

+0

यह समझ में आता है। तरीके (ग्राहक विधियां) घटनाओं से अधिक लचीली होती हैं, और कम समस्याग्रस्त भी होती हैं (उदा। घटना से संबंधित स्मृति रिसाव)। दूसरी तरफ, विधियों को एक कदम पीछे की तरह लग रहा है, क्योंकि प्रोग्रामर को कॉलबैक संग्रहित एक सूची को भी लागू करना है, कॉलबैक सूची की थ्रेड-सुरक्षा के बारे में चिंता करें। तो ऐसा लगता है कि सामान्य रूप से, घटनाएं अभी भी सादे _subscriber_ विधियों (यहां ईएपी के बारे में बात नहीं करते) पर बेहतर हैं, और ग्राहक विधियां आमतौर पर इसके लायक नहीं हैं (उदाहरण के लिए विशेष कॉलबैक व्यवहार निर्दिष्ट करते समय)। जवाब के लिए धन्यवाद! – ShdNx

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