Skip to content

Asenkron Programlama

Genel Bakış

Asenkron programlama, uygulamanın uzun süren işlemleri (I/O, ağ istekleri, veritabanı sorguları vb.) sırasında thread'leri bloke etmeden çalışmasını sağlayan bir programlama modelidir. Bu sayede uygulama daha responsive ve ölçeklenebilir hale gelir.

Temel Kavramlar

1. Async/Await Pattern

public class OrderService
{
    private readonly IOrderRepository _repository;
    private readonly ILogger<OrderService> _logger;

    public OrderService(
        IOrderRepository repository,
        ILogger<OrderService> logger)
    {
        _repository = repository;
        _logger = logger;
    }

    public async Task<Order> GetOrderAsync(int id)
    {
        try
        {
            _logger.LogInformation("Getting order {Id}", id);

            // Asenkron veritabanı sorgusu
            var order = await _repository.GetByIdAsync(id);

            if (order == null)
            {
                _logger.LogWarning("Order {Id} not found", id);
                return null;
            }

            // Asenkron hesaplama
            await CalculateOrderTotalAsync(order);

            _logger.LogInformation("Order {Id} retrieved successfully", id);
            return order;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting order {Id}", id);
            throw;
        }
    }

    private async Task CalculateOrderTotalAsync(Order order)
    {
        // Uzun süren hesaplama işlemi
        await Task.Run(() =>
        {
            order.Total = order.Items.Sum(item => item.Price * item.Quantity);
        });
    }
}

2. Task Parallel Library (TPL)

public class DataProcessor
{
    private readonly ILogger<DataProcessor> _logger;

    public DataProcessor(ILogger<DataProcessor> logger)
    {
        _logger = logger;
    }

    public async Task ProcessDataAsync(List<DataItem> items)
    {
        // Paralel işleme
        var tasks = items.Select(async item =>
        {
            try
            {
                await ProcessItemAsync(item);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing item {Id}", item.Id);
            }
        });

        await Task.WhenAll(tasks);
    }

    private async Task ProcessItemAsync(DataItem item)
    {
        // CPU-bound işlem
        await Task.Run(() =>
        {
            // Yoğun hesaplama işlemi
            item.Process();
        });

        // I/O-bound işlem
        await SaveItemAsync(item);
    }

    private async Task SaveItemAsync(DataItem item)
    {
        // Dosya I/O işlemi
        await File.WriteAllTextAsync(
            $"item_{item.Id}.json",
            JsonSerializer.Serialize(item));
    }
}

3. Cancellation Token

public class LongRunningOperation
{
    private readonly ILogger<LongRunningOperation> _logger;

    public LongRunningOperation(ILogger<LongRunningOperation> logger)
    {
        _logger = logger;
    }

    public async Task ProcessAsync(CancellationToken cancellationToken)
    {
        try
        {
            // İşlem başladı
            _logger.LogInformation("Operation started");

            // Her adımda iptal kontrolü
            for (int i = 0; i < 10; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();

                await Task.Delay(1000, cancellationToken);
                _logger.LogInformation("Processing step {Step}", i);
            }

            _logger.LogInformation("Operation completed");
        }
        catch (OperationCanceledException)
        {
            _logger.LogInformation("Operation cancelled");
            throw;
        }
    }
}

Best Practices

1. Async/Await Kullanımı

  • Async void'den kaçının
  • ConfigureAwait(false) kullanın
  • Task.WhenAll/WhenAny kullanın
  • Exception handling yapın
  • Deadlock'lardan kaçının

2. Performans Optimizasyonu

  • CPU-bound işlemleri Task.Run ile yapın
  • I/O-bound işlemleri async/await ile yapın
  • Task pooling kullanın
  • Memory allocation'ı minimize edin
  • Thread pool'u yönetin

3. Hata Yönetimi

  • Try-catch bloklarını doğru kullanın
  • AggregateException'ları handle edin
  • Cancellation token'ları kullanın
  • Timeout mekanizmaları ekleyin
  • Retry pattern uygulayın

Sık Sorulan Sorular

1. Async/Await ne zaman kullanılmalıdır?

  • I/O işlemlerinde
  • Ağ isteklerinde
  • Veritabanı sorgularında
  • Dosya işlemlerinde
  • Uzun süren hesaplamalarda

2. Task.Run ne zaman kullanılmalıdır?

  • CPU-bound işlemlerde
  • UI thread'i bloke etmemek için
  • Paralel işleme gerektiğinde
  • Background task'lar için
  • Legacy kod entegrasyonunda

3. Asenkron programlamada hangi hatalar yapılır?

  • Async void kullanımı
  • Deadlock oluşturma
  • Gereksiz Task.Run kullanımı
  • Exception handling eksikliği
  • Cancellation token kullanmama

Kaynaklar