فراخوانی متدها به شکل آسنکرون (نا متقارن) در سرویس های WCF
  در این مقاله به معرفی سه روش معمول فراخوانی متدهای سرویس های WCF می پردازیم
   WCF
   ۱۰۷۵۱
   دانلود
   مرتضی صحراگرد
   ۱۳۹۰/۳/۱۳
ارسال لینک صفحه برای دوستان ارسال لینک صفحه برای دوستان  اضافه کردن به علاقه مندیها اضافه کردن به علاقه مندیها   نسخه قابل چاپ نسخه قابل چاپ

 

در این مقاله به معرفی سه روش معمول فراخوانی متدهای سرویس های WCF می پردازیم.


فراخوانی متدهای یک سرویس  WCF معمولا به شکل متقارن انجام می شود. بدین معنی که وقتی در نرم افزار کلاینت یک متد از سرویس را فراخوانی می نماید، برنامه تا زمانی که اعمال داخل متد در سرویس به طور کامل انجام شود و مقدار برگشتی (در صورتی که متد دارای مقدار برگشتی باشد) به سمت کلاینت ارسال شود، باید منتظر بماند. حال اگر این متد عملیات زمانبری را انجام دهد برنامه ای که این متد را فراخوانی نموده است اصطلاحا Freeze شده و تا زمانی که اجرای متد به طور کامل به پایان نرسد از دسترس خارج می شود (هنگ می کند).

برای رفع این مشکل از دو روش فراخوانی متد ها به شکل آسنکرون یا در یک ترید (Thread) مجزای سفارشی استفاده می شود.

برای درک بهتر مسئله به متد زیر توجه کنید. تصور کنید که این متد در یک سرویس WCF تعریف شده است و عملیات زمانبری را انجام می دهد.

public string GetData()
{
    //...
    // do a long-term operation...
    //
    return "operation done successfully";
}

فراخوانی متد GetData در سمت کلاینت به طور معمول به شکل زیر انجام می شود.

private void btnNormalCall_Click(object sender, EventArgs e)
{
    ServiceClient client = new ServiceClient();
    string result = client.GetData();

    client.Close();

    //show result
    MessageBox.Show(result);
}

مشکلی که قبلا ذکر شد در فراخوانی به شکل بالا موجود است بنابراین ما قصد داریم متد GetData را به شکل آسنکرون فراخوانی کنم تا اجرای متد در یک ترید مجزا انجام شده و رابط کاربری برنامه Freeze نشود. همانطور که احتمالا مستحضر می باشید، به طور کلی فراخوانی به شکل آسنکرون یکی از تکنیک های مهم بالا بردی راندمان برنامه ها می باشد و مورد ما نیز از این قانون مستثنی نمی باشد.

به طور معمول هنگامی که از یک سرویس WCF ارجاع می گیریم، فقط امضای (Signature) متد ها به شکل متقارن توسط پروکسی تولید می شود و در نتیجه باید تنظیماتی انجام دهیم تا امضای متد ها به شکل آسنکرون نیز تولید شود.

برای انجام این کار باید هنگامی که در حال اضافه نموده سرویس مربوطه به برنامه هستید، روی دکمه Advanced کلیک نمایید.



در پنجره ای که باز می شود باید گزینه Generate asynchronous operations را به شکل انتخاب شده در آورده و دکمه OK را کلیک کنید. 



اکنون امضای نامتقارن متد ها نیز توسط پروکسی تولید شده اند و می توانیم به شکل زیر این متد را به شکل آسنکرون فراخوانی کنیم. دقت کنید که واژه Async به انتهای نام متد ها برای تولید متدهای آسکرون اضافه می شود.

private void btnAsyncCall_Click(object sender, EventArgs e)
{
    ServiceClient client = new ServiceClient();

    client.GetDataCompleted += client_GetDataCompleted;

    client.GetDataAsync(client);
}

void client_GetDataCompleted(object sender, GetDataCompletedEventArgs e)
{
    string result = e.Result;

    // retrieve serviceClient object
    ServiceClient client = e.UserState as ServiceClient;

    // close channel if is open
    if (client != null && client.State != CommunicationState.Closed)
    {
        client.Close();
    }

    //show result
    MessageBox.Show(result);
}

در قطعه کد بالا قبل از فراخوانی متد GetDataAsync، رویداد GetDataCompleted را رجیستر نموده ایم تا هنگامی که انجام دستورات متد GatData به طور کامل به پایان رسید، این رویداد فراخوانی شود. دقت کنید که رویداد مورد نظر به اضافه شده کلمه Completed به نام متد به جود می آید.

تذکر:

یاد آوری می شود که در صورتی که قصد دارید فراخوانی های آسنکرون را در برنامه های تحت وب انجام دهید حتما باید در دایرکتیو صفحه گزینه Async=true را اضافه کنید.

روش دیگر برای بالا بردن راندمان برنامه فراخوانی متد در یک ترید سفارشی (Custom Thread) دیگر توسط کلاس Thread می باشد.

در قطعه کد زیر ما این عمل را انجام داده ایم.

private void btnCallInAnotherThread_Click(object sender, EventArgs e)
{

    Thread thread = new Thread(DoOperationMethod);
    thread.Start();
}
void DoOperationMethod()
{
    ServiceClient client = new ServiceClient();
    string result = client.GetData();

    client.Close();

    MessageBox.Show(result);
}

تفاوت موجود بین روش فراخوانی متد ها به شکل آسنکرون و یک ترید سفارشی:

هنگامی که از روش فراخوانی متد ها به شکل آسنکرون استفاده می کنیم، فراخوانی متد در یک ترید دیگر از مجموعه ترید های .NET thread pool انجام می شود. تعداد این ترید ها محدود (و قابل تنظیم) می باشد و در صورتی که تعداد فراخوانی های آسنکرون ما زیاد باشید باید این مسئله را در نظر داشته باشید.

اما هنگام فراخوانی متد در یک ترید سفارشی، این ترید از سیستم عامل گرفته شده و تعداد آن وابسته به منابع سیستم عامل می باشد که معمولا بسیار زیاد تر از تعداد ترید های .NET thread pool می باشد. البته هزینه تولید ترید های سفارشی بیشتر از ترید های  .NET thread pool می باشد. ضمنا مشکل معروف Thread-Safe بودن کنترل ها در روش آسنکرون وجود ندارد در حالیکه قطعا در روش ترید سفارشی موجود است.

قطعه کد کامل این مقاله از لینک بالای صفحه قابل دریافت می باشد.