در شمارههاي پيشين در مورد برنامهنويسي غيرهمزمان (Asynchronous Programming) مطالب متعددي نوشتيم، توضيح داديم كه مزاياي استفاده از اين روش به مراتب بيشتر از برنامهنويسي همزمان (Synchronous Programming) است، اما به همان نسبت تشخيص خطا و مديريت آن نيز به زمان بيشتري نياز دارد و در بعضي مواقع در صورت استفاده نادرست از منابع ممكن است برنامه شما بخوبي كار نكند و خروجي مورد نظر را به شما ندهد.با پيشرفت ساختار پردازندههاي رايانه و ايجاد هستههاي متعدد فيزيكي و مجازي در پردازشگرها اهميت برنامهنويسي Parallel به مراتب بيشتر از قبل شد (پيشتر اين امر در ابر رايانهها مطرح بود نه در رايانههاي شخصي) برنامهنويسان بر آن شدند به سمت برنامهنويسي موازي بروند و براي برنامههاي خود اين امكان را پديد بياورند تا بتوانند براحتي از تمام توان پردازشي رايانه استفاده كنند.در همين زمان پروژهاي در مايكروسافت با نام Parallel Fx ـ كه يك چارچوب كاري براي استفاده از برنامهنويسي موازي بود ـ توسعه داده شد. اين پروژه كه با استفاده از ويژگيهاي نسخه #C توسعه يافته بود به مرور بهتر شد تا جايي كه در دات نت ۴ به عنوان يكي از كتابخانههاي اصلي به شمار رفت. اين پروژه مقدمهاي براي بهتر شدن زبان#C در نسخه ۵ شد.قبل از اينكه در مورد نسخه ۵#C بخواهيم توضيحي بدهيم، مقدمهاي از برنامهنويسي موازي در داتنت را بررسي ميكنيم.در برنامهنويسي همروند شما چند Task را كه هيچ رابطهاي بين آنها نيست در يك محيط همروند اجرا ميكنيد. اين موضوع مشكلات خود را دارد، Taskها از منابع مشترك استفاده ميكند و اين منابع را بين خود به اشتراك ميگذارند. اين امر مشكل منابع اشتراكي را به وجود ميآورد، در واقع Taskهاي شما به صورت Threadهايي است كه از منابع مشترك استفاده ميكند و اين Threadها مشكل deadlock و data race را به وجود ميآورد.اما در برنامهنويسي موازي يك Task به تعدادي Task مرتب به هم تقسيم و در همان محيط همروند اجرا ميشود. شايد فكر كنيم زماني كه اين وظايف در ارتباط با هم هستند بعضي از مشكلات موجود در حالت همروند به قوت خود باقي بماند؛ اما شما چند وظيفه مرتبط به هم ايجاد كردهايد و مشكلي مانند deadlock هنوز به وقت خود باقي است. مساله مهمتر اين است كه خطايابي اين سيستم نسبت به حالت قبلي پيچيده و سختتر است و همين طور ارتباط بين اين وظايف و انتقال اطلاعات بين آنها. اما نگران نباشيد اينجاست كه Parallel Fx به كمك شما ميآيد و مشكلات شما را حل ميكند.در Parallel Fx كلاس Task جاي Thread را گرفته و امكان اجراي موازي كارها را به شما ميدهد و شما ميتوانيد كار خود را به مراتب سريعتر از چند نخي و حتي برنامهنويسي غيرهمزمان انجام دهيد، حال بگذاريد چند مثال در اين مورد بنويسيم تا با اين كتابخانه و كار با آن آشنا شويم.
Task t = Task.Factory.StartNew(() =»
{
Console.WriteLine("I am the first task");
});
var t2 = t.ContinueWith(delegate
{
//simulate compute intensive
Thread.Sleep(5000);
return "Tasks Example";
});
در كد بالا ما يك Task با استفاده از Lambda Expression ايجاد ميكنيم سپس با استفاده از تابع ContinueWith به آن ميگوييم هر زمان كه كارش تمام شد، اين كار را انجام دهد. t2 به صورت غيرموازي اجرا ميشود.در كتابخانه Parallel Fx كلاسهاي متعددي براي كارهاي متفاوت وجود دارد، يكي از آنها كلاس Parallel است كه به شما اجازه ميدهد براحتي حلقههاي طولاني خود را در يك محيط موازي انجام و زمان اجراي آنها را كاهش دهيد:
Stopwatch watch;
watch = new Stopwatch();
watch.Start();
for (int i = 0; i « 10; i++)
{
Thread.Sleep(1000);
}
watch.Stop();
Console.WriteLine("Serial Time: " + watch.Elapsed.Seconds.ToString());
watch = new Stopwatch();
watch.Start();
System.Threading.Tasks.Parallel.For(0, 10, i =»
{
Thread.Sleep(1000);
});
watch.Stop();
Console.WriteLine("Parallel Time: " + watch.Elapsed.Seconds.ToString());
كد بالا دو كار يكسان را ده بار اجرا ميكند. انتظاري كه شما داريد اين است كه زمان هر دو يكسان باشد اما همان طور كه درخروجي خواهيد ديد، زمان حلقه اول كه به صورت همروند اجرا ميشود ده ثانيه و حلقه دوم سه ثانيه است (اين مقدار در سيستمهاي مختلف با هستههاي مختلف متفاوت است).