पीछे पूरा विचार Parallel.ForEach()यह है कि आपके पास थ्रेड्स का एक सेट है और प्रत्येक थ्रेड प्रक्रिया संग्रह का हिस्सा है। जैसा कि आपने देखा, यह साथ काम नहीं करता है async- awaitजहाँ आप async कॉल की अवधि के लिए थ्रेड जारी करना चाहते हैं।
आप ForEach()थ्रेड्स को अवरुद्ध करके "ठीक" कर सकते हैं , लेकिन यह पूरे बिंदु को हरा देता है async- await।
आप क्या कर सकते हैं इसके बजाय TPL Dataflow का उपयोग करें Parallel.ForEach(), जो अतुल्यकालिक Tasks का समर्थन करता है ।
विशेष रूप से, आपके कोड को एक का उपयोग करके लिखा जा सकता है जो TransformBlockप्रत्येक आईडी को लैम्बडा के Customerउपयोग से बदल देता है async। इस ब्लॉक को समानांतर में निष्पादित करने के लिए कॉन्फ़िगर किया जा सकता है। आप उस ब्लॉक को लिंक करेंगे aActionBlockCustomer जो कंसोल में प्रत्येक को लिखता है। ब्लॉक नेटवर्क सेट करने के बाद, आप Post()प्रत्येक आईडी को TransformBlock।
कोड में:
var ids = new List<string> { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
var getCustomerBlock = new TransformBlock<string, Customer>(
async i =>
{
ICustomerRepo repo = new CustomerRepo();
return await repo.GetCustomer(i);
}, new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
});
var writeCustomerBlock = new ActionBlock<Customer>(c => Console.WriteLine(c.ID));
getCustomerBlock.LinkTo(
writeCustomerBlock, new DataflowLinkOptions
{
PropagateCompletion = true
});
foreach (var id in ids)
getCustomerBlock.Post(id);
getCustomerBlock.Complete();
writeCustomerBlock.Completion.Wait();
यद्यपि आप शायद की समानता को सीमित करना चाहते हैं TransformBlock कुछ छोटे स्थिरांक । इसके अलावा, आप की क्षमता को सीमित कर सकते TransformBlockहैं और आइटम का उपयोग करके इसे अतुल्यकालिक रूप से जोड़ सकते हैं SendAsync(), उदाहरण के लिए यदि संग्रह बहुत बड़ा है।
आपके कोड की तुलना में एक अतिरिक्त लाभ के रूप में (यदि यह काम किया गया है) यह है कि लेखन किसी एकल आइटम के समाप्त होते ही शुरू हो जाएगा, और तब तक प्रतीक्षा न करें जब तक कि सभी संसाधन समाप्त नहीं हो जाते।