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

برنامه نویسی Parallel در سی شارپ :: آشنایی با کلاس Task در سی شارپ

0 نظرات

در قسمت قبل گفتیم که بوسیله کلاس Parallel و متدهای For و ForEach عملیات پردازش بر روی مجموعه ها را به صورت Parallel انجام دهیم. اما بحث Parallel Programming به همین جا ختم نمی شود و راه های دیگری نیز برای برنامه نویسی Parallel وجود دارد. یکی از این روش ها استفاده از کلاس Task است که این کلاس نیز در فضای نام System.Threading.Tasks قرار دارد. حالت های مختلفی برای استفاده از این کلاس وجود دارد که ساده ترین آن استفاده از خصوصیت Factory و متد StartNew است که در زیر نمونه ای از نحوه ایجاد یک Task را مشاهده می کنید:

Task.Factory.StartNew(() =>
{
    Console.WriteLine("Task Started in Thread {0}", Thread.CurrentThread.ManagedThreadId);
    for (int i = 1; i <= 100; i++)
    {
        Console.WriteLine(i);
        Thread.Sleep(500);
    }
});

بوسیله کد بالا، یک Task جدید ایجاد شده که اعداد 1 تا 100 را در یک thread جداگانه در خروجی چاپ می شود. دقت کنید که بعد از اجرای برنامه شناسه Thread ای که Task در آن اجرا می شود با شناسه Thread اصلی برنامه متفاوت است. راهکار بعدی ایجاد یک شئ از روی کلاس Task و ارجرای آن است، در کد زیر Task بالا را به صورت ایجاد شئ ایجاد می کنیم:

Task task = new Task(() =>
{
    Console.WriteLine("Task Started in Thread {0}", Thread.CurrentThread.ManagedThreadId);
    for (int i = 1; i <= 100; i++)
    {
        Console.WriteLine(i);
        Thread.Sleep(500);
    }
});

task.Start();
Console.ReadKey();

زمانی که Task جدیدی ایجاد می کنید بوسیله متد Start که برای کلاس Task تعریف شده است می توانید عملیات اجرای Task را شروع کنید. یکی از خصوصیت های تعریف شده در کلاس Task، خصوصیت IsCompleted است که بوسیله آن می توان تشخیص داد که Task در حال اجرا است یا خیر:

Task task = new Task(() =>
{
    Console.WriteLine("Task Started in Thread {0}", Thread.CurrentThread.ManagedThreadId);
    for (int i = 1; i <= 100; i++)
    {
        Console.WriteLine(i);
        Thread.Sleep(500);
    }
});

task.Start();
while (!task.IsCompleted)
{
                
}

دریافت خروجی از کلاس Task


می توان برای کلاس Task یک خروجی مشخص کرد، فرض کنید می خواهیم Task ای بنویسیم که میانگین حاصل جمع اعداد 1 تا 100 را حساب کرده و به عنوان خروجی بازگرداند. برای اینکار می بایست از کلاس Task که یک پارامتر جنریک دارد استفاده کنیم. ابتدا یک متد به صورت زیر تعریف می کنیم:

public static int CalcAverage()
{
    int sum = 0;

    for (int i = 1; i <= 100; i++)
    {
        sum += i;
    }

    return sum/100;
}

در قدم بعدی می بایست یک Task جنریک از نوع int تعریف کنیم و به عنوان سازنده نام متد تعریف شده را به آن ارسال کنیم:

Task<int> task = new Task<int>(CalcAverage);
task.Start();

Console.WriteLine("Average: {0}", task.Result);

در کلاس بالا بعد از Start کردن Task، بوسیله خصوصیت Result می توانیم نتیجه خروجی از Task را بگیریم، دقت کنید که زمانی که می خواهیم مقدار خروجی را از Task بگیریم، برنامه منتظر می شود تا عملیات Task به پایان برسد و سپس نتیجه در خروجی چاپ می شود.

به این موضوع توجه کنید که بوسیله متد StartNew نیز می توان Task هایی که پارامتر خروجی دارند تعریف کرد:

var task = Task.Factory.StartNew<int>(CalcAverage);

کد بالا دقیقاً کار نمونه قبلی را انجام می دهد، فقط به جای ایجاد شئ Task و فراخوانی آن، از متد StartNew استفاده کردیم.


ارسال پارامتر به Task ها


یکی از قابلیت های Task ها امکان ارسال State به متدی است که قرار است به عنوان Task اجرا شود. برای مثال، فرض کنید در مثال قبلی که Task ایجاد شده حاصل میانگین را حساب کرده و به عنوان خروجی بر میگرداند می خواهیم عدد شروع و پایان را مشخص کنیم، برای اینکار ابتدا یک کلاس به صورت زیر تعریف می کنیم:

public class TaskParameters
{
    public int Start { get; set; }
    public int Finish { get; set; }
}

در ادامه کد متد CalcAverage را به صورت زیر تغییر می دهیم:

public static int CalcAverage(object state)
{
    var parameters = (TaskParameters) state;
    int sum = 0;

    for (int i = parameters.Start; i <= parameters.Finish; i++)
    {
        sum += i;
    }

    return sum/100;
}

در قدم بعدی باید روند ساخت شئ Task را به گونه ای تغییر دهیم که پارامترهای مورد نظر به عنوان state به متد CalcAverage ارسال شوند، برای اینکار به عنوان پارامتر دوم سازنده کلاس Task شئ ای از نوع TaskParameters به صورت زیر ارسال می کنیم:

Task<int> task = new Task<int>(CalcAverage, new TaskParameters()
{
    Start = 100,
    Finish = 1000
});

با انجام تغییرات بالا، توانستیم شئ ای را به عنوان State به Task ارسال کنیم، همچنین توجه کنید که امکان ارسال State بوسیله متد StartNew در خصوصیت Factory نیز وجود دارد. در این بخش با کلاس Task آشنا شدیم، در قسمت بعدی با نحوه متوقف کردن Task ها در زمان اجرا و کلاس CancellationToken آشنا می شویم.

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