فصل 33 از 40 درس 1 از 1

برنامه‌نویسی ناهمگام با async و await

برنامه‌نویسی ناهمگام با async و await

بخشی از آموزش جامع C# و .NET 10

محتوای درس برنامه‌نویسی ناهمگام با async و await

Async Programming برای عملیات I/O مانند فایل، شبکه و پایگاه داده از Block شدن Thread جلوگیری می‌کند. async و await کد ناهمگام را با ساختار خوانا و قابل مدیریت ارائه می‌کنند.

۱. Task و Task<T>

Task نماینده عملیات در حال اجرا یا آینده است و Task<T> نتیجه‌ای از نوع T تولید می‌کند.

مثال

static async Task<int> Load()=>{await Task.Delay(50);return 42;}
         Console.WriteLine(await Load());

در این مثال، مفهوم «Task و Task<T>» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۲. async و await

async امکان استفاده از await را فراهم می‌کند و await ادامه متد را پس از تکمیل Task زمان‌بندی می‌کند.

مثال

await Task.Delay(50); Console.WriteLine("Done");

در این مثال، مفهوم «async و await» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۳. I/O-bound و CPU-bound

async برای I/O-bound بسیار مؤثر است. برای CPU-bound ممکن است Parallelism یا Task.Run در لایه مناسب مطرح شود.

مثال

string text=await File.ReadAllTextAsync("data.txt");

در این مثال، مفهوم «I/O-bound و CPU-bound» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۴. Exception

Exceptionهای Task هنگام await مانند کد همگام قابل مدیریت‌اند.

مثال

try
         {
             await Task.Delay(50);
             throw new InvalidOperationException("Async failure");
         }
         catch (InvalidOperationException ex)
         {
             Console.WriteLine(ex.Message);
         }

در این مثال، مفهوم «Exception» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۵. CancellationToken

عملیات طولانی یا I/O بهتر است در صورت امکان Cancellation را بپذیرند تا فراخواننده کنترل Lifecycle داشته باشد.

مثال

using var cts=new CancellationTokenSource(100);
         try{await Task.Delay(1000,cts.Token);}catch(OperationCanceledException){}

در این مثال، مفهوم «CancellationToken» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۶. ConfigureAwait

در بسیاری از Applicationهای مدرن نیاز مستقیم کمی دارد، اما مفهوم Context برای کتابخانه‌ها و UIها مهم است.

مثال

await Task.Delay(10).ConfigureAwait(false);

در این مثال، مفهوم «ConfigureAwait» در یک قطعه کد مستقل نمایش داده شده است. مقدارها و نام‌ها عمداً ساده انتخاب شده‌اند تا رفتار اصلی قابل مشاهده باشد؛ در پروژه واقعی همین الگو با مدل دامنه، اعتبارسنجی و مدیریت خطای متناسب ترکیب می‌شود.

۷. مثال‌های عملی

static async Task<string> LoadAsync(string path, CancellationToken ct)
         {
             return await File.ReadAllTextAsync(path, ct);
         }

این نمونه عملی چند مفهوم فصل را در کنار هم قرار می‌دهد و برای مشاهده رفتار واقعی کد قابل اجرا و تغییر است.

Task<string> a = File.ReadAllTextAsync("a.txt");
         Task<string> b = File.ReadAllTextAsync("b.txt");
         string[] results = await Task.WhenAll(a, b);

این نمونه عملی چند مفهوم فصل را در کنار هم قرار می‌دهد و برای مشاهده رفتار واقعی کد قابل اجرا و تغییر است.

۸. خطاهای رایج

• استفاده از .Result یا .Wait بدون دلیل

• async void به‌جز Event Handler

• نادیده گرفتن Cancellation در عملیات طولانی

۹. نکات اجرایی

• نام‌ها، Typeها و Methodها را متناسب با مفهوم دامنه و بدون ابهام انتخاب کنید.

• هشدارهای کامپایلر و Nullable را بدون بررسی خاموش نکنید.

• منطق هر بخش را تا حد امکان کوچک، قابل تست و مستقل از I/O غیرضروری نگه دارید.

۱۰. تمرین عملی

برنامه‌ای بسازید که چند فایل را به‌صورت همزمان با Task.WhenAll بخواند و مجموع تعداد کاراکترها را نمایش دهد.

۱۱. جمع‌بندی

در این فصل، مبانی «برنامه‌نویسی ناهمگام با async و await» با تمرکز بر ساختارهای اصلی زبان، الگوهای صحیح استفاده و خطاهای رایج بررسی شد. تسلط بر این مفاهیم زمینه لازم برای اتصال موضوع به فصل‌های بعدی و طراحی کدهای خواناتر، قابل نگهداری و قابل تست را فراهم می‌کند.