تكرار السؤال: …
الإجابة المختصرة
تمثل مكرراً غير متزامن يجمع بين الـ Async والـ Yield، مما يتيح تدفق السجلات للعميل سطراً بسطر فور توفرها دون انتظار تحميل كامل القائمة في الذاكرة.
الشرح
قديماً، كان إرجاع قائمة بيانات ضخمة يتطلب جلب كل السجلات في Task<List<T>> قبل إرسال أول بايت للعميل. باستخدام IAsyncEnumerable<T> وحلقة await foreach، يستطيع السيرفر قراءة السجلات من قاعدة البيانات وتدفقها مباشرة كـ JSON Stream للعميل فور جهوزيتها، مما يخفض زمن استلام أول بايت (TTFB) ويحافظ على ذاكرة السيرفر.
مثال بالكود
[HttpGet("stream")]
public async IAsyncEnumerable<ProductDto> StreamProducts([EnumeratorCancellation] CancellationToken ct) {
await foreach (var p in db.Products.AsAsyncEnumerable().WithCancellation(ct)) {
yield return new ProductDto(p.Id, p.Name);
}
}أخطاء شائعة
- نسيان إضافة سمة [EnumeratorCancellation] لمعامل الـ CancellationToken في دالة الـ IAsyncEnumerable.
أسئلة متابعة
- ما هو دور ConfigureAwait(false) ولماذا كان إلزامياً في تطبيقات المكتب والمكتبات وتغير دوره في ASP.NET Core؟
- كيف تمرر وتتعامل مع CancellationToken في سلاسل استدعاءات الدوال غير المتزامنة بـ ASP.NET Core؟