2013-03-07 29 views
6

का उपयोग करके बहुप्रचारित विधियों को लिखना मेरे पास एक छोटी सी क्वेरी है।एसिंक/प्रतीक्षा में .NET 4.5

मैं मानता हूं कि मैंने नेट 4.5 से पहले बहुप्रतिष्ठण का उपयोग नहीं किया है, लेकिन नई async/await कार्यक्षमता के साथ मैंने इसे आज़माने का फैसला किया। मैंने इसके साथ प्रयोग करना शुरू कर दिया और सब कुछ ठीक लगता है, लेकिन मैं वेब पर कहीं भी "समस्या" के लिए समाधान नहीं ढूंढ पाया।

तो हर किसी को कैसे await नेट मंच के नव तब्दील तरीकों के साथ इस्तेमाल किया जा सकता समझाने (जैसे WriteAsync(), ReadAsync() आदि ...), लेकिन क्या हुआ अगर मैं अपने खुद के तरीकों के लिए इसका इस्तेमाल करते हैं करना चाहते थे? उदाहरण के लिए, मान लें कि मैं एक बेहद महंगा गणना कर रहा हूं और अपने सभी 4 कोर काम कर रहा हूं। मैं यह करने के लिए कुछ इसी तरह होगा:

async Task DoLotsOfWork<T>(T[] data, int start, int end) 
{ 
    //Do very expensive work 
} 

लेकिन चूंकि मैं एक await कीवर्ड वहाँ नहीं है, विधि सिर्फ एक तुल्यकालिक एक के रूप में व्यवहार किया जाता है। मैं इसे बाहर से 4 बार कॉल करना चाहता हूं ताकि यह मेरे सभी कोरों पर चल सके, जबकि मैं उपयोगकर्ता को कुछ समझदार दिखाता हूं (उदा। "कृपया प्रतीक्षा करें ...")। एकमात्र समाधान जिसे मैं समझने में सक्षम था, विधि की शुरुआत में await Task.Yield(); जोड़ना था। कुछ ऐसा:

async Task DoLotsOfWork<T>(T[] data, int start, int end) 
{ 
    await Task.Yield(); 
    //Do very expensive work 
} 

उस स्थिति में, विधि व्यवहार करेगी जैसा कि मैं अपेक्षा करता हूं। लेकिन क्या इसके लिए एक बेहतर समाधान है? मुझे लगता है कि कोड की उस पंक्ति को लिखने से यह आसान/अधिक समझदार होना चाहिए। मैं समझता हूं कि मैं Task/Thread ऑब्जेक्ट बना सकता हूं और Start() विधि पर कॉल कर सकता हूं, लेकिन इसके लिए और भी अधिक काम की आवश्यकता है। मैंने सोचा कि नई async/प्रतीक्षा कार्यक्षमता के साथ इस तरह की चीज आसान होगी।

+4

नई async/इंतजार पैटर्न multithreading प्रदान नहीं करता है। यह केवल आपके वर्तमान धागे को अवरुद्ध करने वाले संचालन को संभालने के लिए क्लीनर कोड प्रदान करता है। – Freeman

+0

कीवर्ड का मतलब यह नहीं है, "मेरे सभी कोर का उपयोग करें"। वे बस संकलक और रनटाइम को बताते हैं कि एक ऑपरेशन को एक अलग थ्रेड पर किया जा सकता है। यदि वहां 4 ऑपरेशन होते हैं जो एक साथ चल सकते हैं तो वे 4 अलग-अलग कोर पर चल सकते हैं। – Jodrell

+0

आप इस [एसिंक्रोनि बनाम concurrency] (http://stackoverflow.com/questions/4844637/what-is-the-difference-between-concurrency-parallelism-and-asynchronous-methods) पर एक नज़र डालना चाहते हैं, async प्रतीक्षा करें Multithreading के साथ मदद नहीं करता है। यह भी एक सिरे मशीनों के लिए उपयोगी है। – Aron

उत्तर

13

तो शुरू करने के लिए आप के साथ एक विधि है कि बहुत महंगा काम तुल्यकालिक करता है की आवश्यकता होगी:

public void DoLotsOfWork<T>(T[] data, int start, int end) 
{ 
    Thread.Sleep(5000);//placeholder for real work 
} 

फिर हम Task.Run उपयोग कर सकते हैं एक ThreadPool धागे में इस कार्य के कई उदाहरण शुरू करने के लिए।

List<Task> tasks = new List<Task>(); 
for(int i = 0; i < 4; i++) 
{ 
    tasks.Add(Task.Run(()=>DoLotsOfWork(data, start, end)); 
} 

फिर हम एक गैर अवरुद्ध इंतजार जब तक उन सभी को किया जाता है कर सकते हैं:

await Task.WhenAll(tasks); 
+0

वैकल्पिक रूप से, 'समांतर' वर्ग का उपयोग करें, जो * समानांतर प्रसंस्करण के लिए डिज़ाइन किया गया है। –

+2

@StephenCleary मुद्दा यह है कि परिणामों को पूरा होने तक समानांतर विधियों को अवरुद्ध कर दिया जाता है, इसलिए आप 'समानांतर 'के लिए' या 'Foreach' को' कार्य में फेंकने की आवश्यकता समाप्त कर देते हैं।रन करें 'यदि आप वर्तमान में हैं, तो यूआई संदर्भ कहें और कार्यों को पूरा होने तक अवरुद्ध नहीं कर सकते। – Servy

+1

@ सर्वी: सच। लेकिन 'समानांतर' का लाभ यह स्वचालित रूप से आपके उपलब्ध कोर का सर्वोत्तम उपयोग करने के लिए कार्य को विभाजित करेगा। जैसा कि आपने कहा था, आप समान कार्य का प्रतिनिधित्व करने वाले 'कार्य' प्राप्त करने के लिए इसे 'कार्य' रुन 'में लपेट सकते हैं। –