ESC را فشار دهید تا بسته شود

TurboPlusTurboPlus عاشق دنیای تکنولوژی، برنامه‌نویسی و همیشه مشتاق یادگیری چیزهای جدید؛ گاهی هم دل‌مشغول دوبیتی‌ها

همه چیز درباره‌ی ConfigureAwait در C#

در برنامه‌نویسی ناهمگام (asynchronous programming) با زبان C#، یکی از مفاهیمی که گاهی باعث سردرگمی توسعه‌دهندگان می‌شود، استفاده از متد ConfigureAwait است. در این مقاله قصد داریم به صورت کامل و عملی به بررسی ConfigureAwait بپردازیم، کاربرد آن را توضیح دهیم، تفاوت ConfigureAwait(true) و ConfigureAwait(false) را شرح دهیم و در نهایت نکاتی مهم برای استفاده صحیح از آن در پروژه‌ها ارائه کنیم.

زمانی که در C# از متدهای ناهمگام (مانند async Task) استفاده می‌کنیم، به‌طور پیش‌فرض ادامهٔ اجرای کد پس از اتمام عملیات، روی همان context قبلی انجام می‌شود؛ مثلاً در برنامه‌های دسکتاپ (مثل WPF یا WinForms) این context همان UI Thread است. این رفتار می‌تواند در برخی موارد موجب کاهش کارایی یا حتی ایجاد deadlock شود.

متد ConfigureAwait به ما اجازه می‌دهد تعیین کنیم که آیا ادامهٔ عملیات ناهمگام باید روی همان context قبلی انجام شود یا خیر.

await SomeAsyncMethod().ConfigureAwait(false);

تفاوت ConfigureAwait(true) و ConfigureAwait(false)

  • ConfigureAwait(true) (پیش‌فرض): ادامهٔ کد پس از await روی همان context اجرا می‌شود.
  • ConfigureAwait(false): ادامهٔ کد روی هر context در دسترس اجرا می‌شود (نیازی به UI Thread یا context قبلی نیست).

مثالی ساده:

public async Task LoadDataAsync()
{
    var data = await GetDataFromApiAsync().ConfigureAwait(false);

    // این خط دیگر روی UI Thread اجرا نمی‌شود!
    // اگر بخواهیم به UI دست بزنیم، باید به Dispatcher ارجاع دهیم.
    UpdateUi(data); // خطرناک!
}

چرا باید از ConfigureAwait(false) استفاده کنیم؟

استفاده از ConfigureAwait(false) مزایایی دارد، به‌ویژه در اپلیکیشن‌هایی که UI ندارند مانند:

  • سرویس‌های وب (ASP.NET Core)
  • سرویس‌های ویندوز (Windows Services)
  • برنامه‌های کنسولی

مزایا:

  1. کاهش استفاده از منابع سیستم: چون لازم نیست حتماً به context اصلی برگردد.
  2. کاهش احتمال Deadlock: به‌ویژه در اپلیکیشن‌هایی که context محدود دارند، مثلاً در ASP.NET کلاسیک.
  3. افزایش سرعت اجرا: چون context switch اتفاق نمی‌افتد.

چه زمانی نباید از ConfigureAwait(false) استفاده کنیم؟

اگر کدی که پس از await اجرا می‌شود باید به UI یا context خاصی (مثل HttpContext در برخی نسخه‌های ASP.NET) دسترسی داشته باشد، نباید از ConfigureAwait(false) استفاده کنید.

مثال:

var result = await GetDataAsync().ConfigureAwait(false);

// این خط نیاز به UI Thread دارد
myLabel.Text = result; // خطرناک در WPF/WinForms

یک مثال عملی

فرض کنیم می‌خواهید داده‌ای را از یک API دریافت کرده و سپس پردازش کنید:

public async Task<string> GetUserNameAsync()
{
    using (var client = new HttpClient())
    {
        var response = await client.GetStringAsync("https://api.example.com/user")
                                   .ConfigureAwait(false);

        return ProcessResponse(response); // اینجا نیازی به UI context نداریم
    }
}

نکات پایانی

  • در برنامه‌های ASP.NET Core، استفاده از ConfigureAwait(false) همیشه توصیه می‌شود چون این نوع برنامه‌ها از SynchronizationContext استفاده نمی‌کنند.
  • در اپلیکیشن‌های UI (مانند WPF)، استفاده از ConfigureAwait(false) می‌تواند باعث بروز خطا شود اگر پس از آن به UI دسترسی داشته باشید.
  • بهتر است از ConfigureAwait(false) در لایه‌های پایین‌تر (مثل کلاس‌های داده‌ای یا شبکه) استفاده شود و در لایه‌های UI از همان context اصلی استفاده شود.

نتیجه‌گیری

متد ConfigureAwait ابزاری قدرتمند در دنیای برنامه‌نویسی ناهمگام C# است که اگر به درستی از آن استفاده شود، می‌تواند باعث بهبود کارایی، کاهش خطاها و افزایش پایداری برنامه‌ها شود. به‌طور کلی:

  • اگر به context اصلی نیاز ندارید → از ConfigureAwait(false) استفاده کنید.
  • اگر به context (مثل UI یا HttpContext) نیاز دارید → از ConfigureAwait(true) یا هیچ چیز استفاده نکنید.

Turbo Plus

سلام! من یه عاشق تکنولوژی‌ام، برنامه‌نویسی رو زندگی می‌کنم و همیشه دنبال یادگیری چیزهای جدیدم. هر وقت چیزی یاد می‌گیرم که به نظرم ممکنه برای بقیه هم جالب یا مفید باشه، اینجا باهاتون به اشتراک می‌ذارم. راستی، فقط با صفر و یک سر نمی‌کنم... عاشق دوبیتی هم هستم! یه بیت شعر خوب، بعضی وقتا بیشتر از یه کتاب آموزش الهام‌بخشه.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *