تبلیغات
شمع آنلاین=منبع دانلود - C# 5.0 و برنامه نویسی غیرهمزمان! - قسمت اول

C# 5.0 و برنامه نویسی غیرهمزمان! - قسمت اول

نویسنده : Admin شنبه 23 مهر 1390 04:49 ب.ظ  •    ارسال شده در: آموزش c#

#C

در مقاله قبلی از سری C# 5.0، تصویری از ویژگی های احتمالی نسخه بعدی سی شارپ ترسیم شد. پس از PDC 2010، آندرس هلسبرگ - معمار و طراح اصلی سی شارپ - برنامه نویسی غیرهم زمان را به عنوان ویژگی دیگری از نسخه بعدی معرفی كرد. در این مقاله برنامه نویسی غیرهمزمان مورد بحث و بررسی قرار می گیرد.

آندرس هلسبرگ - معمار، طراح و سرپرست تیم سی شارپ- در ارائه جالب و دیدنی خود تحت عنوان The Future of C# and Visual Basic در PDC 2010 ویژگی جدیدی از نسخه بعدی سی شارپ ارائه كرد. این ویژگی جدید Asynchronous Programming یا به عبارتی برنامه نویسی غیرهمزمان می باشد. بنابراین عنوان جدیدی به نمودار تكاملی سی شارپ اضافه شده است.



در این مقاله سعی بر آن است تا به معرفی برنامه نویسی غیرهمزمان پرداخته شود. در مقاله بعدی جزئیات بیشتری از نحوه پیاده سازی این ویژگی جدید بیان خواهد شد.

برنامه نویسی غیرهمزمان چیست؟

برای مقایسه برنامه نویسی همزمان (كه همیشه از آن استفاده می كنیم) با برنامه نویسی غیرهمزمان و درك تفاوت این دو به تصویر زیر دقت كنید.

 


فرض كنید می خواهیم اطلاعاتی را دانلود كرده و سپس به پردازش و تحلیل آنها بپردازیم. دو خط كد اولی كه در تصویر بالا مشاهده می كنید، با فراخوانی توابع DownloadData و ProcessData سناریوی ما را پیاده سازی می كنند. همانطور كه مشاهده می شود داده های دانلود شده درقالب متغیر data به عنوان آرگومان به تابع ProcessData فرستاده می شوند. اجرای برنامه تا زمان دانلود كامل data منتظر خواهد ماند. این بازه با رنگ قرمز و علامت STOP مشخص شده است و غیرقابل استفاده می باشد. پس از اتمام دانلود داده ها، اجرای ProcessData آغاز می شود. این روند برنامه نویسی همزمان می باشد. یعنی اجرای برنامه تا قبل از اتمام كامل یك تابع نمی تواند ادامه پیدا كند و سراغ تابع دیگری برود.

در برنامه نویسی غیرهمزمان سناریوی بالا به گونه ای دیگر پیش می رود. به بخش دوم تصویر بالا دقت كنید. دانلود داده ها را به تابعی به نام DownloadDataAsync واگذار كرده ایم، تابع ProcessData به عنوان یك آرگومان (delegate) از این تابع در نظر گرفته شده است. انتظار داریم كه با انجام این فراخوانی، اجرای برنامه ادامه پیدا كند و زمانی كه عمل دانلود كامل شد تابع ProcessData فراخوانی شود. همانطور كه در نوار فراخوانی ها نیز دیده می شود، پس از فراخوانی تابع DownloadDataAsync، پردازش های دیگری انجام شده و با اتمام دانلود داده ها، فراخوانی ProcessData آغاز می شود.

مدل های برنامه نویسی غیرهمزمان (Asynchronous Programming Models)

حال این سوال مطرح می شود كه آیا برنامه نویسی غیرهمزمان بحث جدیدی است یا اینكه مدل های برنامه نویسی غیرهمزمان در دات نت فریم ورك وجود داشته اند؟ در پاسخ باید گفت كه دات نت فریم ورك از چندین مدل برنامه نویسی غیرهمزمان پشتیبانی می كند. به جدول زیر توجه كنید:



بسیاری از كلاس های دات نت فریم ورك، نسخه هایی از توابع رایج خود را تحت عنوان BeginXxx و EndXxx ارائه می دهند. به عنوان مثال كلاس FileStream كه امكان كار با فایل ها را فراهم می كند، دو تابع Read و Write دارد. این دو تابع نسخه های همزمان هستند و فراخوانی آنها باعث می شود كه اجرای برنامه تا اتمام عمل خواندن از فایل یا نوشتن در فایل منتظر بماند. اگر دقت كنید (و شاید هم تاكنون استفاده كرده باشید) این كلاس دو تابع دیگر تحت عناوین BeginRead و BeginWrite در اختیار قرار می دهد. برای روشن تر شدن مطلب به تعاریف زیر دقت كنید:

public override IAsyncResult BeginRead(byte[] array, int offset,
    int numBytes, AsyncCallback userCallback, object stateObject);

public override int EndRead(IAsyncResult asyncResult);

public override int Read(byte[] array, int offset, int count);

همانطور كه مشاهده می شود، تابع BeginRead به عنوان نسخه غیرهمزمان، یك delegate از نوع AsyncCallback دریافت می كند كه هنگام اتمام عمل خواندن، فراخوانی می شود.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
  
namespace AsynchronousTest
{
    internal class Program
    {
        private const string FilePath = @"c:\test.dat";
  
        private static void Main(string[] args)
        {
            // آغاز تست نوشتن غیرهمزمان
            Program.PdTestWrite();
  
            // انتظار برای تكمیل شدن عملیات
            Thread.Sleep(60000);
        }
  
        private static void PdTestWrite()
        {
            // به منظور استفاده از نسخه های غیرهمزمان از
            // FileOptions.Asyncronous
                 // استفاده شده است
            FileStream fs = new FileStream(Program.FilePath, FileMode.OpenOrCreate,
                FileAccess.Write, FileShare.None, 8, FileOptions.Asynchronous);
  
            string content = "A quick brown fox jumps over the lazy dog";
            byte[] data = Encoding.Unicode.GetBytes(content);
  
            // آغاز نوشتن محتوا در فایل
            Console.WriteLine("Begin to write");
            fs.BeginWrite(data, 0, data.Length, Program.OnWriteCompleted, fs);
            // دقت داشته باشید كه پس از فراخوانی تابع بالا بلافاصله خط كد زیر اجرا می شود

            Console.WriteLine("Write queued");
        }
  
        private static void OnWriteCompleted(IAsyncResult asyncResult)
        {
            // پایان عملیات غیرهمزمان
            FileStream fs = (FileStream)asyncResult.AsyncState;
            fs.EndWrite(asyncResult);
  
            // بستن استریم فایل
            fs.Close();
            Console.WriteLine("Write completed");
  
            // تست خواندن غیرهمزمان از فایل
            Program.PdTestRead();
        }
  
        private static void PdTestRead()
        {
            
            // به منظور استفاده از نسخه های غیرهمزمان از
            // FileOptions.Asyncronous
                 // استفاده شده است
            FileStream fs = new FileStream(Program.FilePath, FileMode.OpenOrCreate,
                FileAccess.Read, FileShare.None, 8, FileOptions.Asynchronous);
  
            byte[] data = new byte[1024];
  
            // آغاز خواندن غیرهمزمان محتوا از فایل
            Console.WriteLine("Begin to read");
            // ارسال داده ها و آبجكت فایل به عنوان آبجكت وضعیت
            fs.BeginRead(data, 0, data.Length, Program.OnReadCompleted, new { Stream = fs, Data = data });
       // دقت داشته باشید كه پس از فراخوانی تابع بالا بلافاصله خط كد زیر اجرا می شود
            Console.WriteLine("Read queued");
        }
  
        private static void OnReadCompleted(IAsyncResult asyncResult)
        {
            dynamic state = asyncResult.AsyncState;
  
            // اتمام خواندن از فایل
            int bytesRead = state.Stream.EndRead(asyncResult);
  
            // به دست آوردن محتوا
            byte[] data = state.Data;
            string content = Encoding.Unicode.GetString(data, 0, bytesRead);
             
            // نمایش محتوا و بستن استریم
            Console.WriteLine("Read completed. Content is: {0}", content);
            state.Stream.Close();
            Console.ReadKey();
        }
    }
}

به دو خط از توضیحات كه با رنگ مشخص شده اند دقت كنید. این توضیحات مرز فراخوانی های غیرهمزمان را مشخص می كنند. خروجی زیر موید این مطلب است كه اجرای برنامه منتظر اتمام كار توابع نمانده و ادامه پیدا می كند.



اگر علاقمند به مشاهده باقی مثال های مدل های برنامه نویسی غیرهمزمان باشید، این مقاله را مطالعه كنید. (مثال بالا نیز از مجموعه مثال های این مقاله برگزیده شده است. به منظور یكسان سازی مثال های ارائه شده در مقالات وب سایت، پیشوند Pd به ابتدای توابع اضافه شده است.)

#C و برنامه نویسی غیرهمزمان

جدول مدل های برنامه نویسی غیرهمزمان نشان می دهد كه تاكنون زبانهای دات نت مستقیما از برنامه نویسی غیرهمزمان پشتیبانی نمی كردند. دات نت فریم ورك 4.0 و ارائه شدن كتابخانه پردازش های موازی ( كه در سری مقالات دانت نت فریم ورك 4.0 در مورد آن صحبت خواهیم كرد) بستر لازم برای پشتیبانی مستقیم برنامه نویسی غیرهمزمان توسط سی شارپ و دیگر زبان های دات نت را فراهم كرده است.

دو كلمه كلیدی async و await امكان برنامه نویسی غیرهمزمان در زبان سی شارپ را فراهم خواهند كرد.
  • برای مشخص كردن توابع غیرهمزمان از كلمه كلیدی async استفاده می شود.
  • بخش هایی از تابع غیرهمزمان كه اجرا منتظر اتمام آنها نخواهد ماند، با برچسب await مشخص می شوند.
نحوه تعریف توابع غیرهمزمان در سی شارپ را با یك مثال ساده ادامه می دهیم. فرض كنید كه تابعی برای دریافت فایل صوتی در شبكه اینترنت به شكل زیر تعریف كرده ایم:

public void PdSoundPlayerLoad()
        {
            SoundPlayer player = new SoundPlayer("http://pdsample/sample_files/test.wav");
 
            Console.WriteLine("Loading sound...");
            // اجرای برنامه تا زمان لود شدن كامل فایل در این قسمت منتظر خواهد ماند
            player.Load();
 
            Console.WriteLine("Playing sound.");
            player.Play();
        }

از آنجایی كه تابع Load نسخه همزمان بارگذاری فایل از مسیر داده شده می باشد، تاخیری در اجرای برنامه تا زمان لود شدن كامل آن به وجود خواهد آمد. حال نسخه غیرهمزمان تابع را به شكل زیر بازنویسی می كنیم:


public
async void AsyncPdSoundPlayerLoad()
        {
            SoundPlayer player = new SoundPlayer("http://pdsample/sample_files/test.wav");
 
            Console.WriteLine("Loading sound...");
       // به كامپایلر اطلاع می دهد كه منتظر اتمام این فراخوانی نشده و اجرا ادامه پیدا كند await
            await player.LoadTaskAsync();
 
            Console.WriteLine("Playing sound.");
            player.Play();
        }

async باعث می شود كه كامپایلر تابع را به صورت غیرهمزمان فراخوانی كند. await نیز همانطور كه در توضیحات اشاره شده است باعث می شود كه اجرا بر روی خط كد مشخص شده توقف نكرده، ادامه پیدا كند. توجه داشته باشید كه اگر در بدنه تابعی كه با async مشخص شده است از await استفاده نشود، تابع تفاوتی با تعریف تابع همزمان نخواهد داشت و فراخوانی آن مانند توابع معمولی انجام خواهد شد. (هنگام كامپایل، warning متناسب نمایش داده خواهد شد)

پیش نمایش برنامه نویسی غیرهمزمان

پس از PDC 2010 نسخه پیش نمایش برنامه نویسی غیرهمزمان توسط مایكروسافت در اختیار عموم علاقمندان قرار گرفت. Visual Studio Async CTP مستندات و مثال های متنوع و جامعی ارائه می دهد. پس از دانلود و نصب آن (بر روی ویژوال استودیو 2010)، امكان برنامه نویسی غیرهمزمان را خواهید داشت! این CTP، علاوه بر فراهم كردن امكان برنامه نویسی غیرهمزمان، پروژه هایی جالب در حوزه های مختلف ارائه می دهد كه تمامی آنها با برنامه نویسی غیرهمزمان پیاده سازی شده اند. یكی از این پروژه ها، 101 مثال برنامه نویسی غیرهمزمان بوده كه در حوزه هایی چون UI، Network و IO مثال های جالبی ارائه كرده است.

منابع برای مطالعه بیشتر


كلام آخر

سعی بر آن بود كه در این مقاله، تصویری از برنامه نویسی غیرهمزمان در ذهن خوانندگان محترم ایجاد شود. در مقاله بعدی نحوه عملكرد و چگونگی پیاده سازی برنامه نویسی غیر همزمان بیان خواهد شد. از همراهان گرامی، همكاران عزیز و خوانندگان ارجمند وب سایت، خواهشمند است ما را از نقطه نظرات و پیشنهادات خود بهره مند سازند. همراهی و استقبال شما، مشوق گرمی برای ارائه مقالات بعدی خواهد بود.

  نویسنده:الدینف

منیع:persiadevelopers


برچسب ها: آموزش ، آموزش برنامه نویسی ، c# ، آموزش c# ، C# 5.0 و برنامه نویسی غیرهمزمان ،
آخرین ویرایش: دوشنبه 4 مهر 1390 05:07 ب.ظ

 
لبخندناراحتچشمک
نیشخندبغلسوال
قلبخجالتزبان
ماچتعجبعصبانی
عینکشیطانگریه
خندهقهقههخداحافظ
سبزقهرهورا
دستگلتفکر