مقدمه

در درس‌های گذشته دیدیم که مدیریت دستی نخ‌ها می‌تواند پیچیده و مستعد خطا باشد. برای ساده‌سازی برنامه‌نویسی موازی و بهره‌برداری بهینه از پردازنده‌های چندهسته‌ای مدرن، فریم‌ورک .NET یک کتابخانه‌ی سطح بالا و قدرتمند به نام Task Parallel Library (TPL) را معرفی کرده است. TPL که در فضای نام System.Threading.Tasks قرار دارد، به طور هوشمند کارها را بین هسته‌های موجود تقسیم کرده و مدیریت نخ‌ها را از دید برنامه‌نویس پنهان می‌کند. این کتابخانه به ما اجازه می‌دهد تا بر روی منطق موازی‌سازی تمرکز کنیم، نه بر روی جزئیات مدیریت نخ. در این درس، با کلاس استاتیک Parallel به عنوان نقطه‌ی ورود به دنیای TPL آشنا می‌شویم.

کلاس استاتیک `Parallel`

کلاس System.Threading.Tasks.Parallel مجموعه‌ای از متدهای استاتیک را برای پیاده‌سازی الگوهای رایج موازی‌سازی فراهم می‌کند. این کلاس به طور خودکار داده‌ها یا تکرارها را بین چندین نخ از استخر نخ (Thread Pool) تقسیم می‌کند تا به صورت موازی اجرا شوند.

حلقه‌های Parallel.For و Parallel.ForEach

دو مورد از پرکاربردترین متدهای کلاس Parallel، نسخه‌های موازی حلقه‌های for و foreach هستند. این متدها برای سناریوهایی طراحی شده‌اند که در آن‌ها هر تکرار حلقه از تکرارهای دیگر مستقل است.

متد Parallel.For

این متد معادل موازی یک حلقه‌ی for استاندارد است. این متد یک عمل (Action) را برای محدوده‌ای از اندیس‌ها به صورت موازی اجرا می‌کند.

Copy Icon Program.cs
Console.WriteLine("Executing loop in parallel:");
// The loop body (the lambda expression) will be executed for i from 0 to 9.
// The iterations may run on different threads and in a non-sequential order.
Parallel.For(0, 10, i =>
{
    Console.WriteLine($"Iteration {i} running on thread {Thread.CurrentThread.ManagedThreadId}");
    Thread.Sleep(100); // Simulate work
});
Console.WriteLine("Parallel.For has completed.");

اگر این کد را اجرا کنید، خواهید دید که ترتیب چاپ تکرارها تصادفی است و شناسه‌ی نخ‌ها نیز متفاوت است، که نشان می‌دهد تکرارها به صورت موازی بر روی نخ‌های مختلف در حال اجرا هستند.

متد Parallel.ForEach

این متد معادل موازی حلقه‌ی foreach است و یک عملیات را بر روی تمام عناصر یک کالکشن IEnumerable به صورت موازی اجرا می‌کند.

Copy Icon Program.cs
var filesToProcess = new List<string> { "file1.dat", "file2.dat", "file3.dat", "file4.dat" };

// Process each file in the collection in parallel.
Parallel.ForEach(filesToProcess, file =>
{
    Console.WriteLine($"Processing {file} on thread {Thread.CurrentThread.ManagedThreadId}");
    // Simulate processing time
    Thread.Sleep(1000);
});

اجرای موازی چندین عملیات با Parallel.Invoke

اگر چندین عملیات مستقل دارید و می‌خواهید آن‌ها را به صورت موازی اجرا کنید، متد Parallel.Invoke یک راهکار ساده و خوانا ارائه می‌دهد. این متد آرایه‌ای از نمایندگان Action را به عنوان ورودی می‌گیرد، همه‌ی آن‌ها را به صورت موازی شروع کرده و منتظر می‌ماند تا تمام آن‌ها به پایان برسند.

Copy Icon Program.cs
void Task1() { Console.WriteLine("Task 1 is running"); Thread.Sleep(1000); }
void Task2() { Console.WriteLine("Task 2 is running"); Thread.Sleep(1000); }

Parallel.Invoke(
    () => Task1(),
    () => Task2(),
    () => Console.WriteLine("Task 3 is running")
);

Console.WriteLine("All parallel tasks have completed.");

چه زمانی از برنامه‌نویسی موازی استفاده کنیم؟

  • کارهای محاسباتی سنگین (CPU-Bound): کلاس Parallel و TPL برای کارهایی طراحی شده‌اند که به شدت از CPU استفاده می‌کنند، مانند پردازش تصویر، محاسبات علمی، یا الگوریتم‌های پیچیده. موازی‌سازی این کارها می‌تواند زمان اجرا را به طور چشمگیری کاهش دهد.
  • کارهای وابسته به I/O: برای کارهایی که منتظر یک عملیات ورودی/خروجی (I/O) می‌مانند (مانند خواندن از فایل یا انتظار برای پاسخ شبکه)، استفاده از کلاس Parallel رویکرد بهینه‌ای نیست. این کار باعث اشغال شدن بی‌مورد نخ‌های Thread Pool می‌شود. برای این سناریوها، باید از برنامه‌نویسی ناهمزمان با async و await استفاده کرد که در درس‌های آینده به آن می‌پردازیم.
  • هزینه‌ی سربار (Overhead): موازی‌سازی رایگان نیست. تقسیم کار و مدیریت نخ‌ها خود هزینه‌ی پردازشی دارد. برای کارهای بسیار کوچک و سریع، اجرای آن‌ها به صورت موازی ممکن است از اجرای ترتیبی (sequential) کندتر باشد.
  • ایمنی نخ (Thread Safety): مهم‌ترین نکته این است که کلاس Parallel مشکل شرایط رقابتی را حل نمی‌کند. اگر تکرارهای موازی شما به داده‌های مشترکی دسترسی دارند، شما همچنان مسئول همگام‌سازی آن دسترسی با استفاده از lock یا دیگر مکانیزم‌های همگام‌سازی هستید.