2013-07-02 12 views
31

मान लीजिए कि हमारे पास आई/ओ बाध्य विधि है (जैसे डीबी कॉल बनाने की विधि)। यह विधि सिंक्रनाइज़ और असीमित रूप से दोनों में चलाया जा सकता है। यही कारण है,कार्य। फैक्टरी। स्टार्टन्यू बनाम कार्य। फैक्टरी। फ्रॉमएसिंक

  1. सिंक:

    IOMethod() 
    
  2. Async:

    BeginIOMethod() 
    EndIOMethod() 
    

फिर जब हम अलग अलग तरीकों से विधि पर अमल के रूप में नीचे दिखाया गया है, में प्रदर्शन क्या फर्क है संसाधन उपयोग की शर्तें?

  1. var task = Task.Factory.StartNew(() => { IOMethod(); }); 
    task.Wait(); 
    
  2. var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ...); 
    task.Wait(); 
    
+2

संक्षिप्त उत्तर, आप (शायद) थ्रेड पूल थ्रेड नहीं रखते हैं, वहां से 'FromAsync' का उपयोग करते समय कुछ भी नहीं कर रहे हैं, तो आप हैं यदि आप 'StartNew' का उपयोग करते हैं। यदि आप बहुत सारी चीज़ें कर रहे हैं, तो थ्रेड पूल पर जोर देना एक प्रदर्शन समस्या हो सकती है। – Servy

+0

डुप्लिकेट: http://stackoverflow.com/questions/5018897/tpl-taskfactory-fromasync-vs-tasks-with-blocking-methods – shambulator

उत्तर

53
var task = Task.Factory.StartNew(() => { IOMethod(); }); 
task.Wait(); 

यह Wait() की वजह से अपने वर्तमान धागा ब्लॉक जबकि IOMethod() निष्पादित हो रहा है एक धागा पूल धागा ब्लॉक और भी होगा (svick के जवाब देखें।)। कुल अवरुद्ध धागे: 2।

var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ...); 
task.Wait(); 

हो जाएगा ताकि (सबसे अधिक संभावना) में अतुल्यकालिक एक धागा का उपयोग किए बिना कार्रवाई करने, लेकिन यह Wait() की वजह से वर्तमान धागा रोकेंगे। कुल अवरुद्ध धागे: 1.

IOMethod(); 

जबकि IOMethod() निष्पादित हो रहा है यह वर्तमान धागा रोकेंगे। कुल अवरुद्ध धागे: 1.

यदि आपको वर्तमान धागे को अवरुद्ध करने की आवश्यकता है, या यदि इसे अवरुद्ध करना आपके लिए ठीक है, तो आपको इसका उपयोग करना चाहिए, क्योंकि टीपीएल का उपयोग करने की कोशिश करने से वास्तव में आपको कुछ भी नहीं मिलेगा।

var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ...); 
await task; 

यह अतुल्यकालिक रूप से एक धागे का उपयोग किए बिना आपरेशन प्रदर्शन करेंगे, और यह भी आपरेशन await को अतुल्यकालिक रूप से धन्यवाद पूरा करने के लिए, इंतजार करेंगे। कुल अवरुद्ध धागे: 0.

यदि आप एसिंक्रनाइ का लाभ लेना चाहते हैं तो आप इसका उपयोग करना चाहिए और आप सी # 5.0 का उपयोग कर सकते हैं।

var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ...); 
task.ContinueWith(() => /* rest of the method here */); 

यह अतुल्यकालिक रूप से एक धागे का उपयोग किए बिना आपरेशन प्रदर्शन करेंगे, और यह भी आपरेशन ContinueWith() को अतुल्यकालिक रूप से धन्यवाद पूरा करने के लिए, इंतजार करेंगे। कुल अवरुद्ध धागे: 0.

यदि आप एसिंक्रनाइ का लाभ लेना चाहते हैं तो आप इसका उपयोग करना चाहिए और आप सी # 5.0 का उपयोग नहीं कर सकते हैं।

+2

मुझे लगता है कि "task.Wait()" उदाहरण के लिए बस पेश किया गया था। मुझे यकीन है कि जब कार्य निष्पादित हो रहा है, तो ओपी रास्ते में कुछ अतिरिक्त करने का इरादा रखता है। तो मुझे नहीं लगता कि आपको कॉलिंग थ्रेड को अवरुद्ध थ्रेड के रूप में गिनना चाहिए। लेकिन अगर वह सिर्फ इंतजार करने के बारे में गंभीर था, तो आप सही हैं। – Tombala

+0

@ टोंबाला मुझे इस प्रश्न में कुछ भी दिखाई नहीं देता है जो इंगित करेगा। लेकिन यह निश्चित रूप से एक संभावना है। – svick

1

(1) होगा (संभावना) थ्रेड पूल नेट अपने Task कार्रवाई करने के लिए होता है।

(2) जो भी तंत्र आपके BeginIOMethod/EndIOMethod जोड़ी को मूल रूप से एसिंक्रोनस भाग को संभालने के लिए उपयोग करता है, जो .NET थ्रेड पूल को शामिल कर सकता है या नहीं भी उपयोग करेगा।

उदाहरण के लिए, यदि आपके BeginIOMethod इंटरनेट पर टीसीपी संदेश दे रहा है, और बाद में प्राप्तकर्ता प्रतिक्रिया (EndIOMethod द्वारा प्राप्त) में आप एक टीसीपी संदेश भेजने के लिए जा रहा है, तो ऑपरेशन के अतुल्यकालिक प्रकृति है .NET थ्रेड पूल द्वारा प्रदान नहीं किया जा रहा है। इस्तेमाल होने वाली टीसीपी लाइब्रेरी एसिंक्रोनस भाग प्रदान कर रही है।

यह TaskCompletionSource class का उपयोग करके पूरा किया जा सकता है। Task.Factory.FromAsyncTaskCompletionSource<T> बना सकता है, इसे Task<T> लौटाएं, फिर EndIOMethod का उपयोग Result को Task<T> पर रखने के लिए ट्रिगर के रूप में करें जो कॉलिंग के समय Task.Factory.FromAsync फ़ॉर्म को वापस कर दिया गया था।

संसाधन उपयोग के संदर्भ में प्रदर्शन अंतर क्या है?

(1) और (2) के बीच का अंतर मुख्य रूप से यह है कि .NET थ्रेड पूल में इसके वर्कलोड को जोड़ा जा रहा है या नहीं। आम तौर पर, सही काम करने के लिए Task.Factory.FromAsync चुनना है यदि आपके पास केवल Begin.../End... जोड़ी और Task.Factory.StartNew अन्यथा है।


आप सी # 5.0 का उपयोग कर रहे हैं, तो आप गैर-अवरुद्ध await task;task.Wait(); के बजाय का उपयोग कर किया जाना चाहिए।

+0

क्या (2) अभी भी BeginIOMethod निष्पादित करने के लिए थ्रेड लॉन्च करने वाला नहीं है? क्या वह थ्रेड पूल में अभी भी धागा नहीं होगा? [इस सवाल] के मुताबिक (http://stackoverflow.com/questions/7784589/how-does-task-factory-fromasync-work-behave), FromAsync थ्रेड पूल का भी उपयोग करता है। – Tombala

+0

@ टोंबाला 'BeginIOMethod'' थ्रूएसिंक 'कॉलिंग थ्रेड पर पूरी तरह सिंक्रनाइज़ रूप से चलाया जाता है। --- उस प्रश्न के उत्तर पर, यह टिप्पणी देखें: "परिणामस्वरूप कार्य डिफ़ॉल्ट रूप से थ्रेड पूल थ्रेड पर निष्पादित किया जाएगा" - केवल तभी ऑपरेशन को थ्रेड चलाने की आवश्यकता होती है। उदाहरण के लिए, I/O ऑपरेशंस थ्रेड के बजाय I/O समापन पोर्ट का उपयोग करेगा। यह तराजू बेहतर है क्योंकि धागे सीमित और कुछ महंगी संसाधन हैं। –

+0

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

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