درخواست های ارتباط
جستجو تنظیمات
لیست دوستان من

برنامه نویسی Parallel در سی شارپ :: کوئری های Parallel در LINQ

0 نظرات

علاوه بر مواردی که تا کنون پیرامون برنامه نویسی Parallel در دات نت آموختیم امکان نوشتن کوئری های LINQ به صورت Parallel نیز وجود دارد. این قابلیت بوسیله یکسری Extension Method که برای این موضوع تعریف شده امکان پذیر است و اصطلاحاً به کوئری های LINQ که به صورت Parallel اجرا می شوند PLINQ گفته می شود.

اما شیوه اجرای کوئری ها به صورت Parallel چگونه است؟ زمانی که شما از متدهای مربوطه برای اجرای کوئری ها به صورت Parallel استفاده می کنید، PLINQ کوئری مورد نظر را آنالیز کرده و تصمیم میگیرد که اجرای کوئری به صورت Parallel بر روی Performance برنامه شما تاثیر منفی می گذارد یا خیر. کوئری که به صورت Parallel اجرا نشود اصطلاحاً Sequentional گفته می شود و PLINQ به صورت هوشمند نوع اجرای مناسب را برای کوئری شما انتخاب می کند، این موضوع به این معنی است که درخواست اجرای کوئری به صورت Parallel لزوماً تضمینی بر اجرای آن به صورت Parallel نیست و تصمیم این موضوع با آنالیزوری است که کوئری را تحلیل می کند.

متدهای مورد نیاز برای اجرای کوئری ها به صورت Parallel در کلاسی به نام ParallelEnumerable که در فضای نام System.LINQ قرار گرفته تعریف شده اند. در زیر ابتدا نگاهی به این متدها می اندازیم:

  1. متد AsParallel: این متد مشخص می کند که کوئری های بعد از این متد می بایست به صورت Parallel اجرا شوند.

  2. متد WithCancellation: مشخص می کند که در زمان اجرای کوئری به صورت دائم می بایست وضعیت token مشخص شده بررسی شده و در صورت درخواست Cancel کردن کوئری، روند اجرای آن متوقف شود.

  3. متد WithDegreeOfParallelism: مشخص می کند که چه تعداد پردازشگر باید برای اجرای کوئری تخصیص داده شود.

  4. متد ForAll: برای خروجی وضعیتی را فعال می کند که خروجی قبل از ادغام و بازگرداندن آن به Thread اصلی می بایست به صورت Parallel مورد پردازش تکمیلی قرار گیرد، دقیقاً مانند زمانی که نتیجه خروجی یک کوئری LINQ بوسیله دستور foreach مورد پردازش قرار می گیرد.

برای اینکه به صورت عملی با نحوه نوشتن کوئری های LINQ به صورت Parallel آشنا شویم مثال زیر را در نظر بگیرید:

static void Main(string[] args)
{
    Task.Factory.StartNew(ProcessData);

    Console.ReadKey();
}

public static void ProcessData()
{
    var source = Enumerable.Range(1, 1000000).ToArray();

    var evenNumbers = (from number in source where number%2 == 0 orderby number descending select number).ToArray();

    Console.WriteLine("Found {0} even numbers in source.", evenNumbers.Length);
}

در مثال بالا و در متد ProcessData، ابتدا بوسیله متد Range از کلاس Enumerable یک آرایه از اعداد 1 تا 1000000 ایجاد کردیم و در قدم بعدی بوسیله یک کوئری LINQ اعداد زوج را بدست آوردیم و در نهایت در خروجی تعداد اعداد زوج که بوسیله کوئری استخراج شده اند را در خروجی نمایش دادیم. اما اگر بخواهیم کوئری بالا به صورت Parallel اجرا شود می بایست بوسیله کوئری LINQ را به صورت زیر تغییر دهیم و از متد AsParallel استفاده کنیم:

var evenNumbers = (from number in source.AsParallel() where number%2 == 0 orderby number descending select number).ToArray();

همانطور که مشاهده می کنید، بعد از نوشتن منبع یعنی source از متد AsParallel برای اجرای کوئری به صورت Parallel استفاده کردیم.


Cancel کردن یک کوئری PLINQ


برای اینکه به کاربر قابلیت کنسل کردن کوئری ها را بدهیم از متد WithCancellation استفاده می کنیم، در ابتدا باید یک شئ از CancellationTokenSource ایجاد کنیم:

private static CancellationTokenSource tokenSource = new CancellationTokenSource();

در قدم بعدی به صورت زیر که در قسمت قبلی آموختیم مکانیزم کنسل کردن کوئری را آموزش می دهیم:

static void Main(string[] args)
{
    Task.Factory.StartNew(ProcessData);
    Console.CancelKeyPress += (sender, eventArgs) =>
    {
        eventArgs.Cancel = true;
        tokenSource.Cancel();
    };
    Console.ReadKey();
}

و در نهایت کد مربوط به کوئری را به صورت زیر تغییر می دهیم:

public static void ProcessData()
{
    var source = Enumerable.Range(1, 1000000).ToArray();

    int[] evenNumbers;

    try
    {
        evenNumbers = (from number in source.AsParallel().WithCancellation(tokenSource.Token) where number%2 == 0 orderby number descending select number).ToArray();
        Console.WriteLine("Found {0} even numbers in source.", evenNumbers.Length);
    }
    catch (OperationCanceledException ex)
    {
        Console.WriteLine(ex);
    }

}

همانطور که مشاهده می کنید در قسمت کوئری و بعد از متد AsParallel از متد WithCancellation برای مشخص کردن token تعریف شده که بواسطه آن کوئری را کنسل می کنیم استفاده کردیم. همچنین قسمت کوئری اصلی را داخل بدنه try..catch گذاشتیم، زیرا در صورت فراخوانی متد Cancel برای شئ tokenSource، کوئری به صورت خودکار خطای OperationCanceledException را تولید می کند (با این مکانیزم در قسمت قبلی آموزش آشنا شدیم.)

با اتمام این بخش مباحث مرتبط با TPL در دات نت نیز به پایان رسید، البته مطالب مرتبط با TPL بسیار گسترده بوده و شاید برای پوشش کل مباحث مرتبط نیاز به نوشتن صدها صفحه مطلب باشد، اما کلیت موضوع را سعی کردیم در این سری مطالب مطرح کنیم. در قسمت بعدی که قسمت نهایی سری مطالب Asynchronous Programming است با کلمات کلیدی async و await که روش ساده تری برای نوشتن برنامه های Asynchronous در اختیار ما قرار می دهند آشنا می شویم.

ITPRO باشید

نویسنده: حسین احمدی

منبع: ITPRO

آیا این مطلب را پسندیدید؟
ردیف عنوان قیمت
1 کار با Thread ها در زبان سی شارپ :: آشنایی با Process ها، Thread ها و AppDomain ها رایگان
2 کار با Thread ها در زبان سی شارپ :: آشنایی با ماهیت Asynchronous در Delegate ها رایگان
3 کار با Thread ها در زبان سی شارپ :: آشنایی با فضای نام System.Threading و کلاس Thread رایگان
4 کار با Thread ها در زبان سی شارپ :: آشنایی با Thread های Foreground و Background در دات نت رایگان
5 کار با Thread ها در زبان سی شارپ :: آشنایی با مشکل Concurrency در برنامه های Multi-Threaded و راهکار های رفع این مشکل رایگان
6 کار با Thread ها در زبان سی شارپ :: آشنایی با کلاس Timer رایگان
7 کار با Thread ها در زبان سی شارپ :: آشنایی با CLR ThreadPool در دات نت رایگان
8 برنامه نویسی Parallel در سی شارپ :: مقدمه ای بر Task Parallel Library و کلاس Parallel در دات نت رایگان
9 برنامه نویسی Parallel در سی شارپ :: آشنایی با کلاس Task در سی شارپ رایگان
10 برنامه نویسی Parallel در سی شارپ :: متوقف کردن Task ها در سی شارپ - کلاس CancellationToken رایگان
11 برنامه نویسی Parallel در سی شارپ :: کوئری های Parallel در LINQ رایگان
12 آشنایی با کلمات کلیدی async و await در زبان سی شارپ رایگان
13 استفاده از متد WhenAll برای اجرای چندین Task به صورت همزمان در سی شارپ رایگان
هیچ نظری ارسال نشده است

برای ارسال نظر ابتدا به سایت وارد شوید

arrow