2011-09-19 13 views
6

बाहर किया जाए या नहीं मैं async तरीकों का उपयोग करना चाहिए नहीं समझ या करने की कोशिश कर जैसे:क्या पहले से ही अलग थ्रेड पर एसिंक प्रारंभ/समाप्ति विधियों का उपयोग करना आवश्यक है?

और

उनके सिंक्रोनस TcpListener.AcceptTcpClient और NetworkStream.Read संस्करणों के विपरीत। मैं संबंधित धागे देख रहा हूं लेकिन मैं अभी भी एक चीज़ के बारे में कुछ अनिश्चित हूं:

प्रश्न: एसिंक्रोनस विधि का उपयोग करने का मुख्य लाभ यह है कि जीयूआई लॉक नहीं है। हालांकि, इन विधियों को अलग Task धागे पर बुलाया जाएगा क्योंकि ऐसा इसलिए कोई खतरा नहीं है। इसके अलावा, TcpListener.AcceptTcpClient एक कनेक्शन बनने तक धागे को अवरुद्ध करता है इसलिए कोई बर्बाद CPU चक्र नहीं होता है। चूंकि यह मामला है, तो इतने सारे हमेशा एसिंक संस्करणों का उपयोग करने की सलाह क्यों देते हैं? ऐसा लगता है कि इस मामले में सिंक्रोनस संस्करण बेहतर होंगे?

इसके अलावा, एसिंक्रोनस विधियों का उपयोग करने का एक और नुकसान बढ़ती जटिलता और वस्तुओं का निरंतर कास्टिंग है। उदाहरण के लिए, यह करने के लिए होने के लिए:

private void SomeMethod() 
{ 
    // ... 

    listener.BeginAcceptTcpClient(OnAcceptConnection, listener); 
} 

private void OnAcceptConnection(IAsyncResult asyn) 
{ 
    TcpListener listener = (TcpListener)asyn.AsyncState; 

    TcpClient client = listener.EndAcceptTcpClient(asyn); 
} 

के रूप में इस का विरोध किया:

TcpClient client = listener.AcceptTcpClient();

भी ऐसा लगता है async संस्करणों वजह से एक और धागा बनाने के लिए होने के लिए और अधिक भूमि के ऊपर होगा। (असल में, प्रत्येक कनेक्शन में धागा होता है और फिर उस धागे को पढ़ने के लिए एक और धागा भी होता है। थ्रेडप्शन!)

इसके अलावा, टीसीपी लिस्टनर की मुक्केबाजी और अनबॉक्सिंग और निर्माण, प्रबंधन और समापन से जुड़े ओवरहेड ये अतिरिक्त धागे।

असल में, जहां आमतौर पर व्यक्तिगत क्लाइंट कनेक्शन को संभालने के लिए व्यक्तिगत धागे होते हैं, अब वहां और उसके बाद प्रत्येक प्रकार के ऑपरेशन के लिए अतिरिक्त थ्रेड होता है (स्ट्रीम डेटा पढ़ना/लिखना और सर्वर के अंत में नए कनेक्शन सुनना)

अगर मैं गलत हूं तो कृपया मुझे सही करें। मैं अभी भी थ्रेडिंग के लिए नया हूं और मैं यह सब समझने की कोशिश कर रहा हूं। हालांकि, इस मामले में ऐसा लगता है कि सामान्य सिंक्रोनस विधियों का उपयोग करना और थ्रेड को अवरुद्ध करना इष्टतम समाधान होगा?

उत्तर

4

TcpListener.AcceptTcpClient एक कनेक्शन बनने तक थ्रेड को अवरुद्ध करता है इसलिए कोई बर्बाद CPU चक्र नहीं होता है।

लेकिन कोई काम नहीं किया जा रहा है। एक थ्रेड एक महंगी ऑपरेटिंग सिस्टम ऑब्जेक्ट है, जो कि सबसे महंगा है। आपका प्रोग्राम कनेक्शन अनुरोध पर थ्रेड ब्लॉक के दौरान उपयोग किए बिना मेमोबाइट मेमोरी का उपभोग कर रहा है।

हालांकि, इन तरीकों अलग टास्क धागे पर बुलाया जाएगा यह तो वहाँ कि

किसी कार्य के कोई खतरा नहीं एक अच्छा समाधान या तो है है के रूप में नहीं है, यह एक ThreadPool धागे लेकिन धागा का उपयोग करता है ब्लॉक करेगा। थ्रेडपूल प्रबंधक मशीन पर सीपीयू कोर की संख्या के बराबर चल रहे टीपी धागे की संख्या रखने की कोशिश करता है। जब टीपी थ्रेड लंबे समय तक ब्लॉक करता है तो यह ठीक से काम नहीं करेगा। यह अन्य उपयोगी कामों को अन्य टीपी धागे द्वारा किया जा रहा है जो उनकी बारी लेने की प्रतीक्षा कर रहे हैं।

BeginAcceptTcpClient() एक तथाकथित I/O पूर्णता कॉलबैक का उपयोग करता है। सॉकेट सुन रहा है, जबकि कोई सिस्टम संसाधनों का उपभोग नहीं किया जाता है। जैसे ही कनेक्शन अनुरोध आता है, ऑपरेटिंग सिस्टम एपीसी (एसिंक्रोनस प्रोसेस कॉल) चलाता है जो कॉलबैक बनाने के लिए थ्रेडपूल थ्रेड को पकड़ता है। थ्रेड स्वयं आमतौर पर कुछ माइक्रोसेकंड के लिए उपयोग में है। बहुत ही कुशल।

कोड इस तरह अगले async के साथ सी # के अगले संस्करण में बहुत आसान हो जाएगा और कीवर्ड का इंतजार है। साल का अंत, शायद।

3

यदि आप पर पर थ्रेड पर AcceptTcpClient() पर कॉल करते हैं, तो वह धागा बेकार है जब तक आप कनेक्शन प्राप्त न करें।

यदि आप BeginAcceptTcpClient() पर कॉल करते हैं, तो कॉलिंग थ्रेड थ्रेड को बर्बाद किए बिना तुरंत बंद कर सकता है।

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

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