Blazor Yaşam Döngüsünde Render Maliyetleri ve Temel Hatalar
Blazor Server ve Blazor Web App mimarilerinde yüksek etkileşimli ekranlar geliştirirken en sık düşülen tuzak, bileşen yaşam döngüsü (lifecycle) metotlarının yanlış kullanılması sonucu oluşan gereksiz yeniden çizimler (re-render) ve sunucu kilitlenmeleridir.
Özellikle kurumsal ölçekteki veri panellerinde veya özel kurumsal yazılım mimarilerinde, yaşam döngüsünün doğru yönetilmemesi hem sunucu kaynaklarını tüketir hem de UI tarafında fark edilir gecikmelere yol açar.
1. Senkron Bloklama ve Deadlock Riski (.Result Tuzağı)
Blazor bileşenleri UI iş parçacığında asenkron çalışacak biçimde tasarlanmıştır. Asenkron bir I/O çağrısını senkron metotlar içinde .Result veya .Wait() ile bekletmek, sunucu thread'ini askıya alır ve sayfa kaynağını görüntülerken (SSR/Prerender) sonsuz döngüye yol açabilir.
Hatalı Yaklaşım
// YANLIŞ: UI Thread'i bloklanır ve prerender kilitlenir
protected override void OnInitialized()
{
// Deadlock ve TaskCanceledException riski taşır
var data = ProductService.GetCatalogAsync().Result;
catalogList = data;
}
Doğru Yaklaşım
// DOĞRU: Asenkron metot override edilir ve await kullanılır
protected override async Task OnInitializedAsync()
{
catalogList = await ProductService.GetCatalogAsync();
}
2. Prerender Sırasında JavaScript Interop Çağrıları
Sunucu tarafında prerendering (SSR) açıkken, tarayıcıda henüz bir DOM veya SignalR devresi oluşmamıştır. OnInitializedAsync aşamasında çağrılan bir JS betiği, sistemin InvalidOperationException fırlatarak durmasına neden olur.
Hatalı Yaklaşım
// YANLIŞ: Prerendering esnasında DOM henüz hazır değildir
protected override async Task OnInitializedAsync()
{
await JS.InvokeVoidAsync("initCustomChart");
}
Doğru Yaklaşım
// DOĞRU: JS interop yalnızca tarayıcı render ettikten sonra ve ilk seferde çalışır
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
try
{
await JS.InvokeVoidAsync("initCustomChart");
}
catch (Exception ex) when (ex is TaskCanceledException or JSDisconnectedException)
{
// Bağlantı kopmaları ve sayfa terklerinde hatayı güvenle yutun
}
}
}
3. OnParametersSet ve Re-render Patlamaları
Dışarıdan parametre alan bileşenlerde (örneğin URL slug'ı dinleyen detay sayfaları), veri yükleme mantığı OnInitializedAsync yerine OnParametersSetAsync içinde ele alınmalıdır. Ancak burada her parametre güncellemesinde kontrolsüz veri çekilmesi sunucuya çift sorgu bindirir.
Hatalı Yaklaşım
// YANLIŞ: Parametre değişmese dahi her render döngüsünde DB'ye gider
protected override async Task OnParametersSetAsync()
{
currentPost = await DbContext.BlogPosts.FirstOrDefaultAsync(p => p.Slug == Slug);
}
Doğru Yaklaşım
// DOĞRU: Parametrenin gerçekten değişip değişmediği kontrol edilir
private string? _cachedSlug;
protected override async Task OnParametersSetAsync()
{
if (_cachedSlug != Slug)
{
_cachedSlug = Slug;
currentPost = await DbContext.BlogPosts.FirstOrDefaultAsync(p => p.Slug == Slug);
}
}
Sonuç: Mimari Standartların Önemi
Blazor mimarisi modern, hızlı ve saf C# ile zengin istemci deneyimi sunar; ancak bileşen döngüsünün arkasındaki mekanizmayı doğru işletmek kritik önem taşır. Yüksek trafikli sistemlerde ölçeklenebilir altyapılar için modern web mühendisliği yaklaşımlarından yararlanmak projenin ömrünü uzatır.
