حسین احمدی
بنیانگذار توسینسو و برنامه نویس و توسعه دهنده ارشد وب

آشنایی با کلاس AutoResetEvent در سی شارپ

تا این قسمت از آموزش با نحوه ایجاد و استفاده از Thread ها آشنا شدیم. اما موقعیتی را در نظر بگیرید که پس از اجرای Thread برنامه باید منتظر شود تا کار Thread در حال اجرا به اتمام رسیده و سپس مابقی عملیات اجرا شود. برای اطلاع از اینکه کار یک Thread به اتمام رسیده راه های زیادی است، اگر از قسمت ماهیت Asynchronous در delegate ها به خاطر داشته باشید، یک فیلد عمومی تعریف کردیم و زمانی که عملیات Thread به اتمام رسید مقدار آن را برابر true قرار دادیم تا در متد Main متوجه شویم عملیات Thread به پایان رسیده است. اما در حالت عادی این راهکار به هیچ عنوان مناسب نیست، زیرا دو Thread در ان واحد به یک متغیر دسترسی دارند و این کار می تواند باعث بروز مشکل در داده های برنامه شود.

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران

در دات نت راهکار دیگری برای اطلاع از اینکه عملیات یک Thread به اتمام رسیده و همچنین Thread-Safe (منظور از Thread-Safe مکانیزمی است که دسترسی دو یا چند Thread به یک متغیر منجر به بروز مشکل در برنامه نشود) نیز می باشد، استفاده از کلاس AutoResetEvent است. برای استفاده از این کلاس به صورت زیر عمل می کنیم:

  1. یک شئ از نوع AutoResetEvent ایجاد کرده و برای سارنده مقدار false را ارسال می کنیم، یعنی هنوز ما Notification ای از جانب شئ ایجاد شده دریافت نکردیم.
  2. سپس در قسمتی که قصد داریم منتظر اتمام اجرای thread باشیم متد WaitOne را در شئ ای که از کلاس AutoResetEvent ایجاد کردیم را فراخوانی می کنیم.
  3. همچنین برای اینکه در Thread مشخص کنیم عملیات به پایان رسیده باید متد Set را برای شئ ایجاد شده از کلاس AutoResetEvent فراخوانی کنیم.

در قسمت قبلی کدی نوشتیم که اعدادی را بر اساس مقادیر ورودی کاربر در خروجی چاپ می کرد. ابتدا در کلاس Program یک شئ به صورت زیر ایجاد می کنیم:

private static AutoResetEvent waitHandle = new AutoResetEvent(false);

در قدم بعدی کد زیر را در متد Main می نویسیم و در قسمتی که می خواهیم منتظر اتمام عمیات thread ایجاد شده باشیم متد WaitOne را فراخوانی می کنیم:

static void Main(string[] args)
{
    ParameterizedThreadStart threadStart = new ParameterizedThreadStart(PrintNumbers);
    Thread thread = new Thread(threadStart);
    thread.Name = "PrintNumbersThread";
    thread.Start(new PrintNumberParameters() {Start = 5, Finish = 13});
    waitHandle.WaitOne();
    Console.WriteLine("PrintNumbers thread is done.");
}

در قدم بعدی متد PrintNumbers را تغییر داده و در انتهای آن، متد Set را به صورت زیر فراخوانی می کنیم:

public static void PrintNumbers(object data)
{
    PrintNumberParameters parameters = (PrintNumberParameters) data;
    for (int counter = parameters.Start; counter < parameters.Finish; counter++)
    {
        Console.WriteLine("Running from thread: {0}", counter);
        Thread.Sleep(500);
    }
    waitHandle.Set();
}

در قسمت بعدی با Thread های Background و Foreground آشنا خواهیم شد. ITPRO باشید

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

منبع: ITPRO


حسین احمدی
حسین احمدی

بنیانگذار توسینسو و برنامه نویس و توسعه دهنده ارشد وب

حسین احمدی ، بنیانگذار TOSINSO ، توسعه دهنده وب و برنامه نویس ، بیش از 12 سال سابقه فعالیت حرفه ای در سطح کلان ، مشاور ، مدیر پروژه و مدرس نهادهای مالی و اعتباری ، تخصص در پلتفرم دات نت و زبان سی شارپ ، طراحی و توسعه وب ، امنیت نرم افزار ، تحلیل سیستم های اطلاعاتی و داده کاوی ...

نظرات