সমান্তরাল.ফোর্চ প্রতিটি বনাম টাস্ক.রুন এবং টাস্ক.ভেনআল


158

সমান্তরাল.ফরএচ বা টাস্ক.রুন () ব্যবহারের মধ্যে পার্থক্যগুলি কি অ্যাসিঙ্ক্রোনিকভাবে কাজগুলির সেট শুরু করতে?

সংস্করণ 1:

List<string> strings = new List<string> { "s1", "s2", "s3" };
Parallel.ForEach(strings, s =>
{
    DoSomething(s);
});

সংস্করণ 2:

List<string> strings = new List<string> { "s1", "s2", "s3" };
List<Task> Tasks = new List<Task>();
foreach (var s in strings)
{
    Tasks.Add(Task.Run(() => DoSomething(s)));
}
await Task.WhenAll(Tasks);

3
আমি মনে করি যে আপনি যদি এর Task.WaitAllপরিবর্তে ব্যবহার করেন তবে 2 য় কোড টুকরা 1 ম এর সমান হবে Task.WhenAll
এড়িয়ে চলুন

15
দয়া করে নোট করুন যে দ্বিতীয়টি তিনবার ডসোমিংথিং ("এস 3") সঞ্চালন করবে এবং এটি একই ফলাফল প্রদান করবে না! stackoverflow.com/questions/4684320/…
নুলিয়াস


@ ড্যান: নোট করুন যে সংস্করণ 2 অ্যাসিঙ্ক / অপেক্ষার ব্যবহার করে, যার অর্থ এটি একটি ভিন্ন প্রশ্ন। সম্ভাব্য সদৃশ থ্রেড লেখার 1.5 বছর পরে, ভিএস 2012-এর সাথে অ্যাসিঙ্ক / অপেক্ষার প্রবর্তন করা হয়েছিল।
পিটার টি

উত্তর:


159

এই ক্ষেত্রে, দ্বিতীয় পদ্ধতিটি ব্লক করার পরিবর্তে কাজগুলি সমাপ্ত হওয়ার জন্য অবিচ্ছিন্নভাবে অপেক্ষা করবে।

তবে, Task.Runএকটি লুপে ব্যবহার করার অসুবিধা রয়েছে- এটির সাথে Parallel.ForEachএকটি প্রয়োজন Partitionerযা প্রয়োজনের চেয়ে বেশি কাজ করা এড়াতে তৈরি হয়। Task.Runসর্বদা আইটেম প্রতি একক টাস্ক তৈরি করবে (যেহেতু আপনি এটি করছেন) তবে Parallelক্লাসের ব্যাচগুলি কাজ করে যাতে আপনি মোট কাজের আইটেমের চেয়ে কম কাজ তৈরি করেন। এটি উল্লেখযোগ্যভাবে আরও ভাল সামগ্রিক কর্মক্ষমতা সরবরাহ করতে পারে, বিশেষত যদি লুপের বডিটিতে প্রতি আইটেমের জন্য কম পরিমাণে কাজ থাকে।

যদি এটি হয় তবে লিখিতভাবে আপনি উভয় বিকল্পকে একত্রিত করতে পারেন:

await Task.Run(() => Parallel.ForEach(strings, s =>
{
    DoSomething(s);
}));

নোট করুন যে এটি এই সংক্ষিপ্ত আকারেও লেখা যেতে পারে:

await Task.Run(() => Parallel.ForEach(strings, DoSomething));

1
দুর্দান্ত উত্তর, আমি ভাবছিলাম যে আপনি কি আমাকে এই বিষয়টিতে একটি ভাল পাঠ্য উপাদানের দিকে নির্দেশ করতে পারেন?
দিমিতর দিমিত্রভ

@ দিমিতরডিমিট্রভ সাধারণ টিপিএল স্টাফের জন্য, রিডকোপসি
রিড

1
আমার প্যারালাল।ফোর প্রতিটি কনস্ট্রাক্ট আমার অ্যাপ্লিকেশনটিকে ক্র্যাশ করছে। আমি এর ভিতরে কিছু ভারী ইমেজ প্রসেসিং করছিলাম। যাইহোক, আমি যখন Task.Run (() => সমান্তরাল। ForEach (....) যুক্ত করেছি; এটি ক্রাশ বন্ধ ছিল। কেন আপনি ব্যাখ্যা করতে পারেন? দয়া করে নোট করুন আমি সিস্টেমে কোরগুলির সংখ্যাতে সমান্তরাল বিকল্পগুলিকে সীমাবদ্ধ করি।
monkeyjump

3
যদি DoSomethingহয় async void DoSomething?
ফ্রান্সেস্কো বোনিজি

1
কি হবে async Task DoSomething?
শান ম্লেয়ান

37

প্রথম সংস্করণ সিঙ্ক্রোনালি কলিং থ্রেডকে ব্লক করবে (এবং এটিতে কিছু কাজ চালাবে)।
যদি এটি কোনও ইউআই থ্রেড হয় তবে এটি ইউআই জমা করে দেবে।

দ্বিতীয় সংস্করণটি থ্রেড পুলে সংশ্লেষজনকভাবে কাজগুলি পরিচালনা করবে এবং কলিং থ্রেডটি সম্পন্ন না হওয়া পর্যন্ত প্রকাশ করবে।

ব্যবহৃত শিডিয়ুলিং অ্যালগরিদমগুলির মধ্যেও পার্থক্য রয়েছে।

মনে রাখবেন যে আপনার দ্বিতীয় উদাহরণটি ছোট করা যেতে পারে

await Task.WhenAll(strings.Select(s => Task.Run(() => DoSomething(s)));

2
এটা করা উচিত নয় await Task.WhenAll(strings.Select(async s => await Task.Run(() => DoSomething(s)));? কাজগুলি (প্রতীক্ষার পরিবর্তে) প্রত্যাবর্তনের সময় আমার সমস্যা ছিল বিশেষত যখন বিবৃতিগুলি usingবস্তু নিষ্পত্তি করার জন্য জড়িত ছিল।
মার্টন কল

আমার প্যারালাল।ফোর প্রতিটি কল আমার ইউআই ক্রাশ করছিল আমি টাস্ক.রুন (() => সমান্তরাল.ফোর্চ (....)) যুক্ত করেছি; এটি এবং এটি ক্র্যাশ সমাধান করেছে।
monkeyjump

0

আমি এটি করা শেষ করেছি, কারণ এটি পড়তে সহজ মনে হয়েছিল:

  List<Task> x = new List<Task>();
  foreach(var s in myCollectionOfObject)
  {
      // Note there is no await here. Just collection the Tasks
      x.Add(s.DoSomethingAsync());
  }
  await Task.WhenAll(x);

আপনি যেভাবে এই কাজটি করছেন তা একের পর এক কার্যকর করা হচ্ছে বা যখন সমস্তগুলি একবারে শুরু করা হচ্ছে?
ভিনিসিয়াস গুবারবার্তো

আমি যতদূর বলতে পারি, আমি যখন "ডোসোমিংথিং সিঙ্ক ()" বলি তখন সেগুলি শুরু হয়। ওয়ালআল যখন না ডাকা হয় ততক্ষণ তাদের কিছুতেই বাধা দিচ্ছে না।
ক্রিস এম

আপনার অর্থ প্রথম "ডসোমিংথিং সিঙ্ক ()" বলা হয়?
ভিনিসিয়াস গুবারবার্তো

1
@ChrisM। এটি ডসোমিংথিংসাইক () এর প্রথম অপেক্ষার অবধি অবরুদ্ধ থাকবে কারণ এটি কার্যকরভাবে আপনার লুপে স্থানান্তর করবে। যদি এটি সিঙ্ক্রোনাস হয় এবং আপনার কোনও টাস্ক ফিরে আসে, সমস্ত কোড একের পর এক চলবে এবং যখন সমস্ত টাস্কগুলি সম্পন্ন হওয়ার জন্য অপেক্ষা করবে
সাইমন বেলঞ্জার

0

আমি প্যারালাল দেখেছি Forএকটি অনুপযুক্তভাবে ব্যবহার করা হয়েছে, এবং আমি এই প্রশ্নে একটি উদাহরণ পেয়েছি যা সাহায্য করবে।

আপনি যখন কনসোল অ্যাপে নীচের কোডটি চালাবেন, আপনি দেখতে পাবেন কীভাবে সমান্তরালে কার্য সম্পাদিত হয়েছে Forফোরাচ কলিং থ্রেডটি ব্লক করে না। আপনি যদি ফলাফলটি (ইতিবাচক বা নেতিবাচক) সম্পর্কে চিন্তা না করেন তবে এটি ঠিক হতে পারে তবে যদি আপনার ফলাফলের প্রয়োজন হয় তবে আপনার অবশ্যই টাস্ক.ভেনআল ব্যবহার করা উচিত।

using System;
using System.Linq;
using System.Threading.Tasks;

namespace ParrellelEachExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var indexes = new int[] { 1, 2, 3 };

            RunExample((prefix) => Parallel.ForEach(indexes, (i) => DoSomethingAsync(i, prefix)),
                "Parallel.Foreach");

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("*You'll notice the tasks haven't run yet, because the main thread was not blocked*");
            Console.WriteLine("Press any key to start the next example...");
            Console.ReadKey();

            RunExample((prefix) => Task.WhenAll(indexes.Select(i => DoSomethingAsync(i, prefix)).ToArray()).Wait(),
                "Task.WhenAll");
            Console.WriteLine("All tasks are done.  Press any key to close...");
            Console.ReadKey();
        }

        static void RunExample(Action<string> action, string prefix)
        {
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine($"{Environment.NewLine}Starting '{prefix}'...");
            action(prefix);
            Console.WriteLine($"{Environment.NewLine}Finished '{prefix}'{Environment.NewLine}");
        }


        static async Task DoSomethingAsync(int i, string prefix)
        {
            await Task.Delay(i * 1000);
            Console.WriteLine($"Finished: {prefix}[{i}]");
        }
    }
}

ফলাফল এখানে:

এখানে চিত্র বর্ণনা লিখুন

উপসংহার:

টাস্ক সহ প্যারালাল.ফোরএচ ব্যবহার করা কলিং থ্রেডকে ব্লক করবে না। আপনি যদি ফলাফলটি সম্পর্কে যত্নশীল হন তবে কাজগুলি অপেক্ষা করতে ভুলবেন না।

~ চিয়ার্স

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.