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

 

تذکر:

برای درک بهتر مطالب این مقاله، آشنایی با مفاهیم پایه سرویس های WCF مورد نیاز می باشد.

مقدمه:

به طور کلی سه نوع الگو (pattern) برای مبادله پیام ها بین سرویس و کلاینت در WCF وجود دارد:

  1. One-Way Operation
  2. Request-response pattern
  3. Duplex pattern

شایع ترین الگوی مورد استفاده در برنامه ها، الگوری Request-response می باشد. سناریو در این الگو بدین شکل می باشد که کلاینت یکی از متدهای سرویس را فراخوانی می کند. سپس منتظر می ماند تا اجرای کد ها در سمت سرویس به پایان برسد و در نهایت نتیجه اجرای متد به سمت کلاینت ارسال می شود و کلاینت به ادامه کار خود می پردازد.

اما مواقعی وجود دارند که متد مورد نظر کلاینت در سمت سرویس دارای مقدار برگشتی نیست و ضمنا برای کلاینت اهمیتی ندارد که اجرای کدها در سمت سرویس با موفقیت انجام شده است یا خیر، و یا حتی نتیجه اجرای متد چه بوده است. در حقیقت در اینگونه مواقع برای کلاینت فقط این موضوع اهمیت دارد که متد مربوطه در سمت سرویس فراخوانده شده و احتمالا پارامتر هایی را برای آن ارسال کند و دیگر نتیجه اجرای متد اهمیتی ندارد.

به عنوان مثال فرض کنید که برنامه ای نوشته اید و قصد دارید در مدت زمان معینی به طور متناوب مشخصات سخت افزاری، تنظیمات، مشخصات پیکربندی، IP کاربر و غیره را جهت جمع آوری آمار  برای شما ارسال شود. بدیهی است که این موضوع هیچ ارتباطی با عملکرد برنامه ندارد و بنابراین نیازی نیست که برنامه کلاینت منتظر این بماند که اجرای متد مربوطه در سمت سرویس به پایان برسد.

آغاز:

یکی از راهکار ها برای اینگونه مواقع، فراخوانی متد ها به شکل یکطرفه (One-Way) می باشد. کلاس OperationContract دارای خصوصیتی به نام IsOneWay می باشد که مقدار پیشفرض آن false است. برای اینکه قابلیت یکطرفه بودن را برای متد فعال کنیم، کافیست که مقدار این خصوصیت را true کنیم.

به مثال زیر توجه کنید:

[ServiceContract]
public interface IHelloService
{
    [OperationContract]
    void DoWork();

    [OperationContract(IsOneWay = true)]
    void DoWorkAsOneWay();
}

در قطعه کد بالا دو متد تعریف شده اند که یکی به شکل معمول بوده و دیگری دارای خصوصیت IsOneWay می باشد.

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

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

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



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




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

اما در فراخوانی متد ها به شکل یکطرفه، کد وضعیت 202 و پیام Accepted ارسال شده است و نشانگر این است که سرویس این درخواست را دریافت کرده است و دیگر هیچ اطلاعی در دسترس نیست.

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

به وجود آمدن خطاهای مدیریت نشده:

نکته قابل تأمل دیگر این است که اگر هنگام اجرای متد های یکطرفه خطای مدیریت نشده ای پیش بیاید، طبق روال سرویس های WCF کانال (Channel) مربوطه fault می شود و دیگر نمی توان از این کانال درخواست های دیگری انجام داد. برای درک بهتر موضوع به مثال زیر توجه کنید.

قطع کد سمت سرویس:

[ServiceContract]
interface IMyContract
{
    [OperationContract(IsOneWay = true)]
    void MethodWithError();

    [OperationContract]
    void MethodWithoutError();
}

class MyService : IMyContract
{
    public void MethodWithError()
    {
        throw new Exception();
    }

    public void MethodWithoutError()
    { }
}

فراخوانی در سمت کلاینت:

MyContractClient proxy = new MyContractClient();

proxy.MethodWithError();

try
{
proxy.MethodWithoutError(); //Will throw because channel faulted
proxy.Close();
}
catch
{}

همانطور که در قطعه کد بالا مشاهده می کنید، به وجود آمدن خطای مدیریت نشده در متد MethodWithError باعث خراب شدن کانال ارتباطی شده و در نتیجه فراخوانی متد MethodWithoutError نیز با شکست روبرو می شود و جالب اینجاست که حتی پروکسی قادر به بستن (Close) ارتباط  به شکل امن نیز نمی باشد.

در انتها یادآور می شویم که پیاده سازی سیستماتیک برنامه با استفاده از قابلیت متدهای یکطرفه به شکل کاملا غیرمتقارن (Asynchronous) نیاز به کارهای بیشتری دارد که شاید در آینده به این مبحث نیز بپردازیم.

برگرفته از:

قطعه کد کامل انجام شده در این مقاله از طریق لینک بالای صفحه قابل دریافت می باشد (VS 2010)