آموزش استفاده از async و await در زبان سی شارپ

  • چهارشنبه ۱۴ آذر ۱۳۹۷
  • بازدید ۱۱,۹۹۲ نفر

تصویر async-and-await-in-csharp_4907 آموزش استفاده از async و await در زبان سی شارپ

آموزش استفاده از async و await در زبان سی شارپ

شما می توانید با استفاده از برنامه نویسی ناهمگام میزان واکنش گرایی و سرعت نرم افزار های خود را به میزان قابل توجهی افزایش دهید. تکنیک های برنامه نویسی همگام و سنتی باعث می شود تا کارکرد نرم افزار پیچیده تر شود و این موضوع اشکال زدایی آن را سخت تر می کند. در نسخه 5 زبان برنامه نویسی C# قابلیت async و await برای برنامه نویسی ناهمگام معرفی شد. در این مقاله آموزش استفاده از async و await در زبان سی شارپ را با استفاده از چند مثال ساده اما کاربردی به شما آموزش خواهیم داد.

بهبود پاسخگویی نرم افزار با async

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

جدول زیر بخش هایی را نشان می دهد که استفاده از async در آن ها باعث بهبود پاسخگویی می شود.

کاربردکلاس های .Net با متدهای asyncکلاس های Windows Runtime با متدهای async
دسترسی به وبHttpClientSyndicationClient
کار با فایل هاStreamWriter, StreamReader, XmlReaderStorageFile
کار با تصاویرMediaCapture, BitmapEncoder, BitmapDecoder
برنامه نویسی WCFSynchronous and Asynchronous Operations

رویکرد برنامه نویسی ناهمگام برای برنامه هایی که دارای UI هستند، بسیار مهم است. فعالیت های مرتبط با UI معمولا در یک thread به اشتراک گذاشته می شوند. اگر یک فعالیت در برنامه نویسی همگام قفل شود، باعث قفل شدن کل فعالیت ها می شود. هنگامی که از برنامه نویسی ناهمگام استفاده کنید، در حین انجام فعالیت های مختلف برنامه شما هنگ نمی کند و می توانید چند کار را باهم انجام دهید.

متدهای async

کلمه کلیدی async و await قلب برنامه نویسی ناهمگام هستند. با استفاده از این دو کلمه کلیدی می توانید از منابع موجود در Windows Runtime، .Net Framework و .Net Core برای ایجاد متدهای async استفاده کنید. نحوه ایجاد متدهای async تقریبا مانند متدهای عادی می باشد با این تفاوت که قبل از نوع باز گشتی متد از کلمه کلیدی async استفاده می شود.

مثال

مثال زیر زیر نحوه پیاده سازی و استفاده از یک متد async در سی شارپ را نشان می دهد. قسمت های مختلف کد با استفاده از کامنت توضیح داده شده است.

توضیحات مثال

سه مورد مهمی که در الگوی متد وجود دارد:

  • کلمه کلیدی async قبل از نوع بازگشتی متد.
  • نوع بازگشتی از نوع Task که در اینجا به صورت Task<int> می باشد زیرا خروجی متد یک عدد صحیح است.
  • نام متد که با کلمه Async خاتمه یافته است.

خروجی متد GetStringAsync یک Task<string>است بنابراین متغیری که خروجی این تابع در آن ذخیره می شود نیز باید از همین نوع باشد. متد DoIndependentWork() کاری را انجام می دهد که به نتیجه بازگشتی از متد GetStringAsync وابسته نیست.

عملگر await اجرای متد AccessTheWebAsync() را معلق می کند و این متد تا زمانی که getStringTask کامل نشده باشد، متوقف می ماند. در همین حال کنترل اجرای برنامه به متدی که AccessTheWebAsync() را فراخوانی کرده است باز می گردد. عملگر await نتیجه Task را از متغیر getStringTask بیرون می کشد و زمانی که عملیات getStringTask کامل شود، کنترل اجرای برنامه به این قسمت باز می گردد تا اجرای برنامه ادامه می یابد.

در آخر دستور return یک عدد صحیح را باز میگرداند و هر متدی که AccessTheWebAsync() را با استفاده از عملگر await فراخوانی کند، این عدد صحیح را می گرد. اگر متد AccessTheWebAsync() کاری به جز دسترسی به وب را انجام ندهد، می توانید کد بالا را به این صورت نیز بنویسید:

نحوه کار متدهای async

شکل زیر نحوه کار متد async مثال بالا را نشان می دهد:

تصویر async-and-await-in-csharp_4907_1 آموزش استفاده از async و await در زبان سی شارپ

توضیحات عکس بالا بر اسا شماره هر قسمت:

  1. یک رویداد که متد AccessTheWebAsync را فراخوانی کرده و با استفاده از عملگر await منتظر پایان کار این متد است.
  2. در داخل متد AccessTheWebAsync یک نمونه از HttpClient ایجاد شده و محتوای سایت با فراخوانی متد GetStringAsync دانلود می شود.
  3. فعالیتی که در داخل متد GetStringAsync انجام می شود، باعث معلق شدن فرآیند اجرای متد می شود. ممکن است منتظر ماندن برای اتمام این فرآیند باعث قفل شده منابع شود. برای جلوگیری از بروز این مشکل متد GetStringAsync کنترل اجرای برنامه را به متدی که آن را فراخوانی کرده است باز می گرداند. متد GetStringAsync یک Task<TResult> باز می گرداند که در مثال بالا Task<string> است. مقدار بازگشتی از این متد در متغیر getStringTask ذخیره می شود.
  4. از آنجا که getStringTask هنوز با عملگر await اجرا نشده است، می توان کار دیگری که به نتیجه بازگشتی متد GetStringAsync وابسته نیست را انجام داد. در مثال بالا متد DoIndependentWork این کار را انجام می دهد.
  5. DoIndependentWork یک متد عادی (synchronous) است و بعد از انجام کار خود به متدی که آن را فراخوانی کرده است باز می گردد.
  6. کنترل اجرای برنامه به متدی که AccessTheWebAsync را فراخوانی کرده است باز می گردد و فعالیت هایی که به نتیجه getStringTask وابسته نیستند را انجام می دهد. زمانی که اجرای Task پایان یابد کنترل اجرای برنامه به AccessTheWebAsync باز می گردد و سایر کدها را اجرا می کند.
  7. رشته موجود در getStringTask (تولید شده توسط متد GetStringAsync) توسط عملگر await گرفته شده و در متغیر urlContents ذخیره می گردد.
  8. حال متد AccessTheWebAsync محتوای سایت را دارد و می تواند طول آن را محاسبه کرده و به عنوان خروجی باز گرداند. سپس کار متد AccessTheWebAsync کامل می شود و برنامه می تواند کار خود را ادامه دهد.

API async methods

ممکن است از خود بپرسید که متدهایی نظیر GetStringAsync که از برنامه نویسی ناهمگام (Asynchronous) پشتیبانی می کنند را چگونه باید پیدا کنم! فریم ورک .Net 4.5 و بالا تر و همچنین .Net Core شامل متدهای زیادی هستند که با استفاده از async و await پیاده سازی شده اند. شما می توانید با پسوند Async موجود در نام این متدها و همچنین نوع خروجی که معمولا Task و Task<TResult> است، آن ها را تشخیص دهید. برای مثال کلاس System.IO.Stream در کنار متدهای synchronous (مانند CopyTo، Read و Write) متدهای Asynchronous (مانند CopyToAsync، ReadAsync و WriteAsync) را نیز شامل می شود.

نخ ها (Threads)

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

async و await

زمانی که شما یک متد را با استفاده از کلمه کلیدی async به یک متد Asynchronous تبدیل می کنید، دو قابلیت زیر در آن متد فعال می شوند:

  • در متد async می توان از عملگر await استفاده کرد. این عملگر به کامپایلر می گوید تا زمانی که عملیات ناهمگام به پایان نرسد نمی تواند کد ها بعد از آن را اجرا کند و کنترل به متد فراخوانی کننده باز گردانده می شود.
  • اجرای متدی ناهمگامی که توسط عملگر await معلق شده است، تا زمان پایان یافتن عملیات مورد نظر ادامه پیدا نمی کند.

به طور عادی در متدهای async یک یا چند عملیات با استفاده از عملگر await انجام می شود. با این حال عدم استفاده از عملگر wait در متدهای async باعث بروز خطا نمی شود ولی کامپایلر در مورد آن هشدار می دهد.

انواع بازگشتی و پارامترها

در حالت عادی خروجی متدهای asynchronous به صورت Task یا Task<TResult> می باشد. در مواقعی که متد شما یک مقدار به عنوان خروجی باز میگرداند (مثلا یک رشته) باید از Task<TResult> استفاده کنید. و زمانی که متد شما هیچ مقدار بازگشتی ندارد یعنی خروجی آن void است باید از Task استفاده کنید.

مثال زیر نحوه اعلان و فراخوانی متدی که خروجی آن از نوع Task یا Task<TResult> می باشد را نشان می دهد.

خروجی یک متد async می تواند به صورت void باشد. این نوع خروجی در event handler ها استفاده می شود.

نکته! متد های async که خروجی آن ها به صورت void می باشد را نمی توان با عملگر await فراخوانی کرد.

نکته! پارامترهای متد async نمی توانند به صورت in، out و ref تعریف شوند.

خروجی های زیر مربوط به متدهای async در Windows Runtime هستند:

  • IAsyncOperation<TResult> که مطابق با Task<TResult> می باشد.
  • IAsyncAction که مطابق با Task می باشد.
  • IAsyncActionWithProgress<TProgress>
  • IAsyncOperationWithProgress<TResult, TProgress>

قوانین نامگذاری متدهای async

در زبان برنامه نویسی سی شارپ بر اساس قوانین نام گذاری، متد هایی که به صورت async باشند، باید در انتهای نام خود از کلمه Async استفاده کنند. این قوانین برای متد ها استفاده می شود و نمی توان در نام گذاری کلاس ها، اینترفیس ها و Event Handler ها از آن استفاده کرد.

مثال کامل

در مثال زیر محتوای تعدادی سایت را با استفاده از کلاس WebClient دانلود می کنیم و سپس طول محتوای هر کدام به همراه میزان زمان سپری شده برای دانلود شدن محتوای همه سایت ها را نشان می دهیم. ظاهر مثال شامل سه عدد Button با نام های BtnSync، BtnAsync و BtnParallelAsync و یک عدد TextBlock در WPF و RichTextBox در WinForms با نام TxtLogs برای نمایش نتایج می باشد.

تصویر async-and-await-in-csharp_4907_2 آموزش استفاده از async و await در زبان سی شارپ

کد مربوط به نسخه WPF این مثال:

محتوای فایل MainWindow.xaml.cs

کد مربوط به نسخه WinForms این مثال:

محتوای فایل Form1.cs

 

باکس دانلود
شناسه:
۴۹۰۷
فرمت فایل:
rar
اندازه فایل:
۱۲۰ کیلوبایت
مطالب مرتبط
ثبت نظر
ریفریش کنید!
نظرات کاربران (۴ مورد)
  1. تصویر آواتار کاربر 0
    یاسین یکشنبه , 19 اسفند

    سوال : اگر ما دوتا تابع داشته باشیم که نوعشان Task await باشد و هردو را باهم فراخوانی کنیم.کانفیلیکتی در اجرا نمیدهد؟

    • تصویر آواتار کاربر 124
      AmRoیکشنبه , 19 اسفند

      سلام...اگه دو تابع وابستگی به هم نداشته باشن، مشکلی بوجود نمیاد.

  2. تصویر آواتار کاربر 0
    امیرحسین چهارشنبه , 8 مرداد

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