পেছনের পুরো ধারণাটি Parallel.ForEach()
হ'ল আপনার থ্রেডগুলির একটি সেট রয়েছে এবং প্রতিটি থ্রেড সংগ্রহের অংশ প্রসেস করে। যেমন আপনি লক্ষ্য করেছেন, এটি async
- এর সাথে কাজ করে না await
, যেখানে আপনি অ্যাসিঙ্ক কলটির সময়কালের জন্য থ্রেডটি প্রকাশ করতে চান।
আপনি "ফিক্স" পারে যে অবরুদ্ধ করে ForEach()
থ্রেড, কিন্তু যে নষ্ট সমগ্র বিন্দু async
- await
।
আপনি যা করতে পারলেন তা হল পরিবর্তে টিপিএল ডেটাফ্লো ব্যবহার করা Parallel.ForEach()
, যা অ্যাসিঙ্ক্রোনাসকে Task
ভাল সমর্থন করে ।
বিশেষত, আপনার কোডটি এমন একটি ব্যবহার করে লেখা যেতে পারে যা TransformBlock
প্রতিটি আইডিকে ল্যাম্বডা Customer
ব্যবহার করে রূপান্তর করে async
। এই ব্লকটি সমান্তরালভাবে সম্পাদন করতে কনফিগার করা যেতে পারে। আপনি সেই ব্লকটিকে এমন একটিতে লিঙ্ক করবেন যা কনসোলে ActionBlock
প্রতিটি লিখেছে Customer
। আপনি ব্লক নেটওয়ার্ক সেট আপ করার পরে, আপনি 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()
, উদাহরণস্বরূপ যদি সংগ্রহ খুব বড় হয়।
আপনার কোডের সাথে তুলনা করার সময় একটি অতিরিক্ত সুবিধা হিসাবে (এটি যদি কাজ করে) হ'ল একক আইটেম শেষ হওয়ার সাথে সাথে লেখাটি শুরু হবে এবং সমস্ত প্রক্রিয়া শেষ না হওয়া পর্যন্ত অপেক্ষা করবেন না।