TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 550 subscribers
Post #782 215
🚨 یک متد Async چطور می‌تواند کل برنامه را بدون هیچ Exceptionای قفل کند؟

یکی از عجیب‌ترین باگ‌هایی که ممکن است در پروژه‌های NET. با آن مواجه شوید این است:
برنامه اجرا می‌شود.
هیچ Exceptionای ندارید.CPU هم لزوماً بالا نیست.
اما یک بخش از برنامه دیگر جلو نمی‌رود.
همه‌چیز منتظر چیزی است...
و آن چیز هم منتظر همان Thread است که شما قفلش کرده‌اید.
به این وضعیت می‌گوییم:🔒 Async Deadlock
🤔 ءDeadlock دقیقاً چطور اتفاق می‌افتد؟

فرض کنید یک متد Async دارید:
public async Task<string> GetDataAsync()
{
await Task.Delay(1000);

return "Hello";
}

و آن را این‌طور صدا می‌زنید:
var result = GetDataAsync().Result;

در ظاهر شاید مشکلی نبینید.
اما در محیط‌هایی که SynchronizationContext وجود دارد، اتفاق زیر ممکن است رخ دهد:
Thread اصلی
│
▼
GetDataAsync()
│
▼
await
│
├── متد کنترل را آزاد می‌کند
│
▼
ءContinuation باید روی Context اصلی ادامه پیدا کند
│
❌
اما Thread اصلی با Result. بلاک شده است
│
▼
Continuation نمی‌تواند اجرا شود
│
▼
.Result منتظر پایان Task است
│
🔒 DEADLOCK

یعنی:
ءTask منتظر Thread است
و Thread منتظر Task

و هیچ‌کدام نمی‌توانند جلو بروند.

☠️ ترکیب خطرناک: await + .Result

مشکل اصلی async نیست.
مشکل زمانی ایجاد می‌شود که:
یک عملیات Async دارید await می‌کنید Continuation باید به یک SynchronizationContext خاص برگردد
اما همان Context را با .Result یا .Wait() بلاک کرده‌اید
مثلاً:
var result = GetDataAsync().Result;

یا:
``lua
GetDataAsync().Wait();``


این دو مورد در چنین سناریوهایی می‌توانند یکی از رایج‌ترین دلایل Deadlock باشند.

🧠 نقش SynchronizationContext چیست؟
وقتی شما می‌نویسید:
await SomeAsyncOperation();

بعضی محیط‌های NET. تلاش می‌کنند بعد از پایان عملیات Async، ادامه متد را دوباره روی همان Context قبلی اجرا کنند.
مثلاً:
UI Thread
│
▼
await
│
▼
عملیات Async
│
▼
بازگشت به UI Thread

این رفتار در محیط‌هایی مثل:
WPF
Windows Forms
ASP.NET کلاسیک
اهمیت زیادی دارد.
چون ممکن است بعد از await نیاز داشته باشید دوباره به Context اصلی برگردید.
اما اگر همان Context را بلاک کنید:
.Result

ءContinuation جایی برای اجرا ندارد.
و برنامه وارد Deadlock می‌شود.

🛠 راهکار اول: Async All the Way
بهترین و مهم‌ترین راهکار این است که عملیات Async را دوباره به عملیات Sync تبدیل نکنید.
❌ این:
public string GetData()
{
return GetDataAsync().Result;
}

بهتر است به این تبدیل شود:
public async Task<string> GetDataAsync()
{
return await _service.GetDataAsync();
}

و در لایه بالاتر:
var result = await GetDataAsync();

قاعده ساده است:
اگر وارد دنیای Async شدید، تا جای ممکن در همان دنیا بمانید.

این همان چیزی است که معمولاً با عنوان:
🚀 Async All the Way
شناخته می‌شود.
🔧 ءConfigureAwait(false) چه کاری انجام می‌دهد؟
فرض کنید یک Library دارید:
public async Task<string> GetDataAsync()
{
await Task.Delay(1000);

return "Hello";
}

به‌صورت پیش‌فرض، در محیط‌هایی که Context وجود دارد، await ممکن است تلاش کند ادامه اجرای متد را روی همان Context قبلی ادامه دهد.
اما با:
await Task.Delay(1000).ConfigureAwait(false);

به سیستم می‌گویید:
بعد از پایان این عملیات، لازم نیست اجرای ادامه متد را روی Context قبلی ادامه بدهی.

مثلاً:
public async Task<string> GetDataAsync()
{
await Task.Delay(1000)
.ConfigureAwait(false);

return "Hello";
}

در نتیجه احتمال گرفتار شدن در Deadlockهای کلاسیک ناشی از SynchronizationContext کاهش پیدا می‌کند.
⚠️ اما آیا باید همه‌جا ConfigureAwait(false) بنویسیم؟
نه دقیقاً.
اگر در یک Application UI هستید و بعد از await می‌خواهید UI را تغییر دهید، ممکن است نیاز داشته باشید به همان Context اصلی برگردید.
مثلاً:
await LoadDataAsync();

// ممکن است نیاز باشد روی UI Thread باشیم
MyLabel.Text = "Loaded";

اما در Libraryها و لایه‌هایی که وابستگی مستقیمی به Context برنامه ندارند، معمولاً عدم وابستگی به Context باعث می‌شود کد قابل‌استفاده‌تر و مستقل‌تر باشد.
به همین دلیل در بسیاری از Libraryها و کدهای زیرساختی، استفاده از:
.ConfigureAwait(false)

یک الگوی رایج است.
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →