IAsyncEnumerable ve await foreach
IAsyncEnumerable ile verileri asenkron olarak akıtın, asenkron yineleyicilerde yield kullanın ve await foreach ile tüketin.
IAsyncEnumerable ve await foreach, CoddyKit'te ücretsiz bir C# Academy dersidir. Bu, 4 dersinin 1. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C# Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C# Academy kursu toplamda 4 dersten oluşur.
IAsyncEnumerable Neden Kullanılır?
IAsyncEnumerable<T> (C# 8 ve .NET Core 3 ile tanıtılmıştır) asenkron akışı mümkün kılar — her şeyi önce belleğe yüklemeden, kullanılabilir hâle geldikçe öğeleri birer birer üretirsiniz. Veritabanı imlecinden satır satır okuduğunuzu veya API yanıtlarını akış hâlinde aldığınızı düşünün.
Asenkron Yineleyici Yazma
IAsyncEnumerable<T> döndüren bir yöntem bildirin ve async yöntemin içinde yield return kullanın. await ve yield return anahtar sözcükleri doğal biçimde birlikte kullanılabilir.
public async IAsyncEnumerable<int> GenerateNumbersAsync(int count)
{
for (int i = 0; i < count; i++)
{
await Task.Delay(100); // simulate async work per item
yield return i;
}
}await foreach ile Tüketme
Bir IAsyncEnumerable<T> değerini await foreach ile tüketin. Her yineleme bir sonraki öğeyi asenkron olarak bekler — tüketici ve üretici doğal bir tempoya göre ilerler.
await foreach (var number in GenerateNumbersAsync(10))
{
Console.WriteLine(number);
}
// With cancellation:
var cts = new CancellationTokenSource();
await foreach (var n in GenerateNumbersAsync(100)
.WithCancellation(cts.Token))
{
if (n > 50) { cts.Cancel(); break; }
Console.WriteLine(n);
}Veritabanından Akış Sağlama
EF Core, sorgu sonuçlarının AsAsyncEnumerable() ile akış hâlinde okunmasını destekler. Bu yöntem, sonuç kümesinin tamamını belleğe yüklemeden satırları birer birer okur — büyük tablolar için kritik önem taşır.
public async IAsyncEnumerable<Product> StreamProductsAsync(
[EnumeratorCancellation] CancellationToken ct = default)
{
await foreach (var product in _db.Products
.Where(p => p.IsActive)
.AsAsyncEnumerable()
.WithCancellation(ct))
{
yield return product;
}
}HTTP Yanıtlarını Akış Hâlinde Alma
Tüm yükü arabelleğe almadan büyük yanıtları istemcilere akış hâlinde gönderin. Sunucu işlemeye devam ederken istemci verileri parça parça alır.
app.MapGet("/stream/products", (ProductRepository repo) =>
{
// Returns an IAsyncEnumerable — ASP.NET Core streams it as JSON array
return repo.StreamAllAsync();
});
// Or with custom serialization:
app.MapGet("/stream/events", async (HttpResponse response, EventStore store) =>
{
response.ContentType = "application/json";
await foreach (var e in store.StreamAsync())
{
await response.WriteAsJsonAsync(e);
await response.Body.FlushAsync();
}
});EnumeratorCancellation Özniteliği
Üreticiye aktarılması için bir asenkron yineleyicinin CancellationToken parametresine [EnumeratorCancellation] uygulayın; böylece tüketici tarafındaki WithCancellation() belirteci üreticiye iletir.
public async IAsyncEnumerable<LogEntry> TailLogAsync(
string logFile,
[EnumeratorCancellation] CancellationToken ct = default)
{
while (!ct.IsCancellationRequested)
{
var newLines = await ReadNewLinesAsync(logFile, ct);
foreach (var line in newLines)
yield return new LogEntry(line);
await Task.Delay(500, ct);
}
}
// Consumer:
await foreach (var entry in TailLogAsync("/var/log/app.log")
.WithCancellation(cts.Token))
{
Console.WriteLine(entry.Message);
}IAsyncEnumerable Üzerinde LINQ
System.Linq.Async NuGet paketi, IAsyncEnumerable için asenkron LINQ işleçleri (WhereAwait, SelectAwait, ToListAsync) sağlar.
// dotnet add package System.Linq.Async
var expensiveProducts = await repo.StreamAllAsync()
.WhereAwait(async p => await pricing.IsExpensiveAsync(p.Id))
.SelectAwait(async p => await enricher.EnrichAsync(p))
.Take(10)
.ToListAsync();
// Or use built-in Where/Select that don't need async:
var names = repo.StreamAllAsync()
.Where(p => p.IsActive)
.Select(p => p.Name);Birden Çok Asenkron Akışı Birleştirme
Birden çok asenkron akışı eş zamanlı işlemek için giriş noktası olarak Channel kullanın — birden çok üreticiden yazın ve tek bir tüketiciden okuyun.
async IAsyncEnumerable<T> Merge<T>(
params IAsyncEnumerable<T>[] streams)
{
var channel = Channel.CreateUnbounded<T>();
var producers = streams.Select(async stream =>
{
await foreach (var item in stream)
await channel.Writer.WriteAsync(item);
});
_ = Task.WhenAll(producers)
.ContinueWith(_ => channel.Writer.Complete());
await foreach (var item in channel.Reader.ReadAllAsync())
yield return item;
}Performans: Arabelleğe Alma ve Akış
Büyük veri kümelerini işlerken her zaman akış kullanın. Önce her şeyi bir listeye yüklemek (ToListAsync()), tüm verileri aynı anda bellekte tutar — akış ise her seferinde tek bir öğeyi işler.
// BAD: loads all 1M records into memory
var allOrders = await _db.Orders.ToListAsync();
foreach (var order in allOrders)
await ProcessAsync(order);
// GOOD: processes one record at a time
await foreach (var order in _db.Orders.AsAsyncEnumerable())
await ProcessAsync(order);
// Memory usage: O(1) vs O(n)Asenkron Yineleyicilerde Hata İşleme
Üreticiden kaynaklanan hataları işlemek için await foreach döngüsünün tamamını bir try/catch içine alın. Yineleyicideki hatalar, o anki yineleme noktasında tüketiciye aktarılır.
try
{
await foreach (var item in RiskyStreamAsync())
{
await ProcessAsync(item);
}
}
catch (HttpRequestException ex)
{
Console.Error.WriteLine($"Stream error: {ex.Message}");
}
catch (OperationCanceledException)
{
Console.WriteLine("Stream cancelled.");
}Hızlı Kontrol
IAsyncEnumerable döndürmenin bir List<T> döndürmeye kıyasla temel bellek avantajı nedir?
Özet: IAsyncEnumerable ve await foreach
Önemli çıkarımlar:
IAsyncEnumerable<T>: öğeleri asenkron olarak, birer birer akış hâlinde işler- Asenkron yöntemlerdeki
yield return, asenkron yineleyiciler üretir await foreach: akışı,.WithCancellation()ile iptal desteği sağlayarak tüketir[EnumeratorCancellation]: tüketicinin belirtecini yineleyiciye aktarır- EF Core: büyük sorgularda bellek verimliliği için
AsAsyncEnumerable()kullanın - Büyük veri kümelerini işlerken
ToListAsync()yerine akış kullanın
Sıkça Sorulan Sorular
“IAsyncEnumerable ve await foreach” dersi ücretsiz mi?
Evet — “IAsyncEnumerable ve await foreach” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C# Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C# Academy kursu toplamda 4 dersten oluşur.
“IAsyncEnumerable ve await foreach” dersinde ne öğreneceğim?
IAsyncEnumerable ile verileri asenkron olarak akıtın, asenkron yineleyicilerde yield kullanın ve await foreach ile tüketin. C# Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
C# Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te C# Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 1. dersidir.
“IAsyncEnumerable ve await foreach” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu C# Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her C# Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- IAsyncEnumerable ve await foreach
- System.Threading.Channels
- ValueTask ve Ayırmalardan Kaçınma
- ConfigureAwait ve Eşitleme Bağlamı