CSCIENCE

CSCIENCE

۲۵ مطلب با موضوع «سیشارپ» ثبت شده است

آشنایی با Task (ادامه)



نوع دوم) انجام عملیاتی دیگر پس از اتمام یک Task
در مثال قبل تنها اجرای یک Task مهم بود و پایان آن اهمیتی نداشت. فرض کنید اینبار می‌خواهیم پس از پایان یک Task کار دیگری (معمولا وابسته به عملیات Task قبلی) انجام دهیم. برای این کار ابتدا لازم است که از پایان یافتن Task با خبر شویم. خوشبختانه دات نت این امکان را فراهم کرده است و شما تنها کافیست به Task بگویید که پس از پایان چه کاری انجام دهد.

2 تابع داریم، یکی DoJob که Task اصلی آن را اجرا می‌کند و دیگری AfterJob که قرار است بعد از پایان DoJob اجرا شود:

public void DoJob()
{
     //Body
}

public void AfterJob()
{
     //Body
}

ابتدا یک ارجاع به Task درحال اجرا ایجاد می‌کنیم:

Task t = Task.Run(() => DoJob());

اکنون تابع AfterJob را برای اجرا بعد از پایان یافتن DoJob به t نسبت می‌دهیم:

t.ContinueWith((tsk) => AfterJob());

که tsk همان ارجاع به Task اصلی است که در اینجا برای استفاده‌های بعدی Capture می‌شود.
هر 2 تابع DoJob و AfterJob می‌توانند هرگونه آرگومان ورودی داشته باشند. در مورد خروجی توابع در پست‌های بعدی بحث خواهیم کرد.
۵ موافقین ۰ مخالفین ۰ ۰۵ فروردين ۹۳ ، ۰۰:۵۵
cscience

آشنایی با Task



قبل از اینکه Async در سیشارپ 5 پدیدار شود، دات نت در فریم‌ورک 4، موجودی(!) به نام Task را معرفی کرد که زیرساخت اصلی Async در سیشارپ 5 است. Task برای راحت‌تر کردن و مدیریت بهتر ناهمگامی بوجود آمده است و امکانات فراوانی را در این زمینه در اختیار برنامه نویس قرار می‌دهد. اگر بخواهیم به‌طور خلاصه شئ Task را تعریف کنیم، می‌توان گفت Task یک عمل در حال اجرا را در خود کپسوله می‌کند و از طریق آن می‌توانیم از وضعیت آن عمل باخبر شویم و یا آن را کنترل کنیم. البته این تعریف خیلی تعریف ساده ایست اما برای شروع مناسب است. در ادامه بیشتر با این موجود آشنا خواهید شد.
هنگامی که شما می‌خواهید یک سری عملیات را به صورت ناهمگام اجرا کنید، کافیست نمونه‌ای از Task ایجاد کنید و مدیریت اجرای آن را به او بسپارید. به محض اینکه عملیات را به Task نسبت می‌دهید، Task یک Thread آزاد را از Thread Pool انتخاب می‌کند و عملیات شما را در آن Thread اجرا می‌کند. ممکن است بپرسید Thread Pool چیست؟
به طور خلاصه می‌توان گفت که دات‌نت برای جلوگیری از هزینه‌های ایجاد و حذف Threadها، مجموعه‌ای از Threadهای آماده به کار را فراهم کرده است و برنامه‌ی شما در صورت نیاز به Thread، می‌تواند از این Threadها استفاده کند. هر Thread بعد از اتمام کار، دوباره به مجموعه باز می‌گردد (برای دریافت کار بعدی).
بنابراین Task به طور اتوماتیک یک Thread از مجموعه انتخاب می‌کند و با آن کار می‌کند و پس از اتمام کار، آن را به مجموعه باز می‌گرداند. اکنون با داشتن یکسری اطلاعات کلی در مورد Task، ادامه‌ی آموزش را با مثال‌های طبقه بندی شده بر اساس نوع عملیات پیش خواهم برد و نکات تکمیلی را اضافه خواهم کرد.

نوع اول) Fire and Go
در این نوع از عملیات، نتیجه‌ی عملیات مهم نیست، فقط قرار است انجام شود و مهم نیست که کی و به چه شکل پایان می‌یابد. از اینجا به بعد یک تابع را به عنوان واحد عملیاتی در نظر خواهیم گرفت و به جای کلمه‌ی عملیات از تابع استفاده می‌کنیم.
فرض کنید تابعی به شکل زیر دارید که قرار است عملیاتی طولانی انجام دهد:

public void DoJob(){
     // Function Body
}

اگر بخواهیم تابع بالا را به روش Fire and Go و به صورت موازی اجرا کنیم، کافیست دستور زیر را اجرا کنیم:

Task.Run(()=>DoJob());

در حالتی هم که تابع مورد نظر، آرگومان ورودی داشته باشد، تنها کافیست هنگام فراخوانی با Task.Run، آرگومان‌ها را در آن بنویسید. به همین سادگی!
در بخش‌های بعدی با انواع مختلف مثال‌ها و ابزارهای مدیریت Task بیشتر آشنا خواهید شد.
۱ موافقین ۰ مخالفین ۰ ۲۵ اسفند ۹۲ ، ۲۱:۵۴
cscience

دلایل استفاده ناهمگامی (Asynchrony)



هنگامی که یکسری عملیات به ترتیب و پشت‌سر هم انجام شوند، به عبارتی، هنگامی که هر عمل بعد از پایان عمل قبلی اجرا شود، می‌گوییم روند اجرای آن‌ها همگام یا Synchronous است. حال اگر شرایط را فراهم کنیم که عملیات مختلف بتوانند بدون انتظار برای پایان دیگر عملیات، شروع به کار کنند (موازی یا همروند)، روند اجرای آن‌ها را ناهمگام یا Asynchronous گوییم. البته این تعریف دقیق نیست و تنها برای ایجاد تصویری مناسب از Asynchrony نوشته شده است. در ادامه به طور خلاصه به چندتا از فواید ناهمگامی اشاره می‌کنم.

1. رابط کاربری (UI)
معروف‌ترین ابزارهای ایجاد رابط‌های کاربری در سیشارپ، Windows Form و WPF هستند. در هر دو تکنولوژی، برای مدیریت رابط کاربری (نمایش اجزا، رخدادها و ...) تنها از یک Thread* استفاده می‌شود. اکنون فرض کنید برنامه‌ی شما قرار است به عنوان مثال بعد از کلیک بر روی یک دکمه، عملیاتی طولانی را شروع کند (محاسبات پیچیده، درخواست‌های تحت شبکه، ورودی/خروجی دیسک و ...). با توجه به اینکه در خواست اجرا از طریق رابط کاربری بوده است و در آن‌جا تنها یک Thread وجود دارد، این عملیات، مدت زمان طولانی Thread مخصوص رابط کاربری را Block می‌کنند و در نتیجه رابط کاربری تا پایان عملیات، توانایی پاسخ‌گویی به کاربر را نخواهد داشت. درست است که عملیات مورد نظر در حال انجام است اما کاربر هیچگاه رابط کاربری از کار افتاده یا Unresponsive را نمی‌پسندد. بهتر است عملیات طولانی در Thread دیگر، موازی با رابط کاربری اجرا شود تا رابط کاربری همواره پاسخ‌گوی کاربر باشد و به نحوی میزان پیشرفت عملیات طولانی را نیز نمایش دهد.

2. استفاده از اوقات بیکاری CPU
گاهی اوقات در برنامه‌ها اعمالی وجود دارند که CPU را درگیر نمی‌کنند (مثل ورودی/خروجی دیسک)، یعنی CPU کار را به واحد دیگر می‌سپارد و منتظر می‌ماند تا آن واحد عملیات مورد نظر را انجام دهد. سپس دوباره به روند اجرای برنامه‌ی اصلی باز می‌گردد. از طرفی اعمالی که واحدهای دیگر انجام می‌دهند، معمولا طولانی و کند هستند و در نتیجه CPU مدت زمان زیادی را بیکار می‌ماند (البته منظور از بیکار بودن اینه که توی اون مدت با برنامه‌ی شما کاری نداره). اگر بتوانیم در این زمان عملیات قسمت دیگری از برنامه را تحویل CPU دهیم، توانسته‌ایم بیشترین استفاده را از CPU ببریم. این مسئله نیز با Asynchrony قابل حل است.

3. استفاده از حداکثر توان پردازشی
سخت‌افزارهایی که امروزه راهی بازار می‌شوند، بسیار قدرتمندتر از آنی هستند که ما (با برنامه‌های معمولی البته) از آن‌ها استفاده می‌کنیم. قلب کامپیوتر یعنی CPU هم از این قضیه مستثنا نیست. CPUهای فعلی حداقل 2 هسته‌ی پردازشی دارند. هسته‌ها می‌توانند قابلیت پردازش موازی و افزایش سرعت برنامه را فراهم کنند. در صورتی که برنامه‌ی شما موازی نباشد، شما تنها از یک هسته CPU استفاده می‌کنید (برای امتحان کافیست برنامه‌ای بنویسید که یک حلقه‌ی طولانی داشته باشد، آن را اجرا کنید و سپس از طریق Task Manager، میزان استفاده از CPU را چک کنید). قابلیت Async در سیشارپ امکان استفاده از همه‌ی هسته‌های پردازشی را به شما می‌دهد.


*مبحث Threadها در این سری آموزشی باز نخواهد شد. برای درک بهتر مفاهیم آموزشی، پیشنهاد می‌کنم از منابع دیگر در مورد Threadها مطالعه کنید.
۱ موافقین ۰ مخالفین ۰ ۲۴ اسفند ۹۲ ، ۱۸:۱۶
cscience

برنامه نویسی Asynchronous به شما اجازه می‌دهد تا بتوانید اعمال مختلف را به صورت همزمان در برنامه‌ی خود پیش ببرید. به عبارت دیگر، این قابلیت از Block شدن برنامه شما، در شرایطی که برنامه در حال انجام کاری طولانی مدت است، جلوگیری می‌کند و باعث می‌شود برنامه‌ Responsive باقی بماند. از دیگر فواید برنامه Asynchronous، می‌توان به استفاده از حداکثر توان سیستم اشاره کرد. امروزه اکثر پردازنده‌ها، چندین هسته‌ی پردازشی دارند که یک برنامه‌ی غیر موازی نهایتا از یک هسته‌ی پردازنده استفاده می‌کند اما با نوشتن یک برنامه‌ی Asynchronous و ایجاد یک الگوی موازی سازی، محاسبات شما به صورت موازی روی هسته‌های مختلف CPU اجرا می‌شود.

سیشارپ یا بهتره بگم دات نت، قابلیت‌ها و روش‌های مختلفی را برای این کار فراهم کرده‌است. یکی از قابلیت‌هایی که در سیشارپ 5 اضافه شده است، کلمات کلیدی async و await است. شما می‌توانید تنها با استفاده از این 2 کلمه کلیدی، برنامه Asynchronous بنویسید! در پست‌های بعدی آموزش مختصر و کوتاهی درباره این قابلیت جدید ارائه خواهم داد.

۰ موافقین ۰ مخالفین ۰ ۲۱ اسفند ۹۲ ، ۱۱:۴۷
cscience

چند وقت پیش برای پروژه‌ی یکی از درس‌ها باید یک مقاله رو پیاده‌سازی می‌کردیم (گروه بودیم). این مقاله روی پیکسل‌های تصویر پردازش انجام می‌داد و چون تعداد تصاویر ورودی زیاد بودن، حجم محاسبات زیاد بود.

اولین پیاده‌سازی ما با متلب بود که زمان اجرایی برابر با 24 ساعت داشت. از اونجایی که متلب به صورت ذاتی کمی کند هست، سراغ سیشارپ رفتیم. پس از اینکه با سیشارپ پیاده سازی انجام شد، مدت زمان اجرا به 8 ساعت رسید که به نظر خیلی خوب بود. کمی بعد یکی از دوستانم که کاملا به دستورات سیشارپ (حتی از نظر کارایی) مسلطه، کد رو بازبینی کرد و دو تغییر زیر را ایجاد کرد:


1. در یک قسمت از برنامه به جای

Math.Pow(x,2)

عبارت x * x را قرار داد.

2. در قسمت دیگری از برنامه، محاسبات با اعداد صحیح کافی بود ولی من از double استفاده کرده بودم، پس بجای آن‌ها از int استفاده کرد.


پس از اجرای برنامه با تغییرات بالا، مدت زمان اجرا به 3 ساعت کاهش یافت. دلیل این اتفاق برای هریک از موارد بالا این است که:


1. تابع Pow در سیشارپ به دلیل اینکه قابلیت توان رساندن اعداد اعشاری را نیز داشته باشد، از روش ضربی استفاده نمی‌کند و بجای آن از روابط دیگری که محاسبات بیشتری لازم دارند استفاده می‌کند. حتی برای توان 2 (البته من فکر می‌کردم این تابع اونقدری هوشمنده که توان‌های صحیح و یا کوچیکو بدونه باید چیکار کنه).

2. محاسبات اعشاری کلا زمان بیشتری نسبت به محاسبات صحیح مصرف می‌کنند.


از این به بعد همیشه به یاد خواهم داشت که تا جای ممکن از محاسبات صحیح استفاده کنم و کارهای ساده‌ی ریاضیو مستقیم کد بزنم و از توابع استفاده نکنم.

۴ موافقین ۰ مخالفین ۰ ۲۷ آذر ۹۲ ، ۱۱:۰۰
cscience

فرض کنید اسم آرایه رشته‌ها temp و اسم لیست names باشد. اکنون داریم


names.AddRange(temp.Select(s => "_" + s + "_"));


تابع AddRange یک مجموعه را به عنوان ورودی میگیره و تمامی اون رو به لیست اضافه میکنه. اما با توجه به سوال، لازمه که تغییر داده شده‌ی رشته‌ها رو اضافه کنیم. که این هم از طریق دستور Select در LINQ به راحتی امکان‌پذیره.


لینک سوال

۱ موافقین ۰ مخالفین ۰ ۱۸ مهر ۹۲ ، ۱۸:۰۵
cscience

در بخش کوتاه نویسی، ابتدا یک مسئله مطرح می‌شه و از شما خواسته می‌شه که کوتاه‌ترین روش‌هاتونو براش بگید. بعد از گذشت چند روز از طرح مسئله، من هم جواب خودم رو می‌نویسم.



سوال:

فرض کنید آرایه‌ای از رشته‌ها داریم و می‌خواهیم تک تک اعضای آن را به یک لیست از رشته‌ها اضافه کنیم و هم‌زمان در ابتدا و انتهای هر رشته، کاراکتر '_' را قرار دهیم. کوتاه ترین روش برای این کار چیست؟


پاسخ

۱ موافقین ۰ مخالفین ۰ ۱۵ مهر ۹۲ ، ۱۵:۱۱
cscience


بخش چهارم: پیاده سازی نمای گرافیکی - بخش پایانی


در این قسمت منطق بازی به گرافیک متصل می‌شود و ساخت بازی کامل می‌شود.
مدت زمان:     30 دقیقه
حجم:           48 مگابایت
کیفیت:         720p
فرمت:          mp4


* آخر این قسمت براتون یه تمرین گذاشتم (:دی). خیلی خوشحال خواهم شد اگر دوستانی که این تمرینو انجام میدن، یک آموزش در قالب فایل متنی بسازند و برای من بفرستن تا من هم برای بقیه روی وبلاگ بذارم.
۳ موافقین ۰ مخالفین ۰ ۲۱ شهریور ۹۲ ، ۱۷:۳۱
cscience


بخش سوم: پیاده سازی بدنه‌ی اصلی بازی


در این قسمت بخش اصلی بازی Snake یعنی ساختمان داده‌ها و الگوریتم‌های بازی رو پیاده سازی می‌کنم
مدت زمان:     30 دقیقه
حجم:           48 مگابایت
کیفیت:         720p
فرمت:          mp4

۱ موافقین ۰ مخالفین ۰ ۱۹ شهریور ۹۲ ، ۰۰:۴۰
cscience

حتما تابه‌حال برنامه‌های زیادی رو دیدید که وقتی عبارتی رو برای جستجو وارد می‌کنید، در همون لحظه همزمان با تایپ شما، نتایج ممکن رو نشون می‌ده. تو این پست قصد دارم با استفاده از امکانات Binding و Linq در #C و WPF این کار رو آموزش بدم.


گام اول: ایجاد TextBox و ListBox

در ابتدا لازمه که برای گرفتن ورودی از کاربر و نمایش نتایج جستجو، از یک عدد TextBox به همراه ListBox استفاده کنیم. نام TextBox را textbox قرار دهید.


گام دوم: تعیین منبع داده

با توجه به اینکه می‌خواهیم از این منبع برای ItemsSource یک ListBox استفاده کنیم، لازم است که جنس آن یک IEnumerable باشد. من در این مثال ابتدا یک کلاس Static تعریف کرده‌ام و سپس در آن یک لیست Static از چند رشته Url ساخته‌ام


static class MyData
    {
        public static List<string> urls = new List<string>
        {
            "cscience.blog.ir",
            "cscience.mihanblog.ir",
            "google.com",
            "bing.com",
            "microsoft.com",
            "bayan.ir",
            "yahoo.com",
            "outlook.com"
        };
    }


گام سوم: نوشتن مبدل رشته به لیست

برای Binding مرحله بعد لازم است که یک مبدل یکطرفه با قابلیت تبدیل رشته (عبارت مورد جستجو) به نتیجه‌ی جستجو نوشته شود


class StringToLinqConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string temp = value as string;
            return MyData.urls.Where(url => url.Contains(temp.Trim())).ToList();
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }


گام چهارم: Bind کردن ItemSource

در نهایت کافیست ItemSource مربوط به ListBox را به مقدار Text کنترل TextBox با استفاده از مبدل مرحله قبل Bind کنیم.


<Window.Resources>
        <local:StringToLinqConverter x:Key="StringToLinqConverter"/>
</Window.Resources>

<ListBox ItemsSource="{Binding Text, Converter={StaticResource StringToLinqConverter}, ElementName=textBox}"/>

اکنون با تایپ کردن عبارت مورد نظر برای جستجو در TextBox تمامی نتایج ممکن همزمان با تایپ حروف نمایش داده می‌شوند.
۰ موافقین ۰ مخالفین ۰ ۱۸ شهریور ۹۲ ، ۲۳:۳۷
cscience