در برنامهنویسی ناهمگام (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)
- برنامههای کنسولی
مزایا:
- کاهش استفاده از منابع سیستم: چون لازم نیست حتماً به context اصلی برگردد.
- کاهش احتمال Deadlock: بهویژه در اپلیکیشنهایی که context محدود دارند، مثلاً در ASP.NET کلاسیک.
- افزایش سرعت اجرا: چون 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)یا هیچ چیز استفاده نکنید.
دیدگاهتان را بنویسید