SemaphoreSlim Sınıfı: C#'ta Çoklu Görevlere Dayalı Programlama

[en] Read in English

2023-06-10

Genel Bakış

SemaphoreSlim sınıfı, bir veya daha fazla threadin aynı anda belirli bir kaynağı veya işlemi kullanmasını kontrol etmek için C# ‘ta kullanılan bir yapıdır. SemaphoreSlim, aynı anda kaynağa erişebilecek thread sayısını sınırlar. SemaphoreSlim kullanımı, genellikle çok threadli uygulamalarda deadlock durumlarını önlemek ve belirli bir kaynağın aynı anda yalnızca bir veya daha fazla thread tarafından kullanılmasını sağlamak için kullanılır.

SemaphoreSlim Kullanımı

SemaphoreSlim sınıfı, aşağıdaki gibi kullanılır:

SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);

Burada ilk parametre, aynı anda kaç threadin kaynağı kullanabileceğini belirler. İkinci parametre, semaphore’un maksimum thread sayısını belirler. Bu örnekte, her iki parametre de 1’dir, bu nedenle aynı anda yalnızca bir thread kaynağı kullanabilir.

Bir iş parçacığı, semaphore’un Wait veya WaitAsync metodunu çağırarak bir kaynağı talep eder:

await semaphore.WaitAsync();

Bir iş parçacığı, semaphore’un Release metodunu çağırarak bir kaynağı serbest bırakır:

semaphore.Release();

Aşağıdaki örnekte SemaphoreSlim kullanımını görebiliriz:

SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

async Task AccessDatabase(string name, int seconds)
{
    Console.WriteLine($"{name} is requesting access to the database");
    await semaphore.WaitAsync();
    Console.WriteLine($"{name} has access to the database");
    await Task.Delay(TimeSpan.FromSeconds(seconds));
    Console.WriteLine($"{name} is done with the database");
    semaphore.Release();
}

AccessDatabase("Task 1", 2);
AccessDatabase("Task 2", 2);

Bu örnekte, “Task 1” ve “Task 2” adlı iki işlem, veritabanına erişmeye çalışıyor. Ancak, semaphore sadece bir işlemin aynı anda veritabanına erişmesine izin verir. Bu nedenle, bir işlem veritabanına erişimini tamamladığında, diğer işlem veritabanına erişebilir.

SemaphoreSlim Diagram

Bu diyagramda, “Task 1” ve “Task 2” adlı iki işlem, bir SemaphoreSlim‘e erişim talep ediyor. SemaphoreSlim sadece bir işlemin aynı anda erişmesine izin verir. Bu nedenle, bir işlem erişimini tamamladığında, diğer işlem erişebilir.

Bir otoparkı düşünün. Otoparka aynı anda belirli sayıda araç park edebilir. Bu durumu, SemaphoreSlim‘in nasıl çalıştığını anlamak için bir analoji olarak kullanabiliriz.

  • Otopark = kaynak (veritabanı, dosya vb.)
  • Arabalar = threadler veya taskler
  • Otoparkın kapasitesi = SemaphoreSlim‘in ilk parametresi
  • Araçların park edebilmesi için bekleyen araç sayısı = SemaphoreSlim‘in ikinci parametresi
  • Araç park etmek için beklerken veya park ettikten sonra = WaitAsync veya Release metodları

Bu benzetme, SemaphoreSlim‘in çok threadli bir uygulamada kaynakların yönetilmesini nasıl sağladığını anlamakta yardımcı olabilir.

SemaphoreSlim‘in Task.WhenAll ve Task.WaitAll ile kullanımı, birden fazla işlemi senkronize etmek için oldukça yaygındır. Bu metodlar, birden fazla Task‘ın tamamlanmasını bekler.

Task.WhenAll ile Kullanımı

Task.WhenAll metodu, birden fazla Task‘ın tamamlanmasını bekler ve bir Task döndürür. Bu Task‘ın tamamlanması, tüm Task‘ların tamamlanmasını gösterir. Aşağıda bir örneğini görebilirsiniz:

SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

async Task AccessDatabase(string name, int seconds)
{
    Console.WriteLine($"{name} is requesting access to the database");
    await semaphore.WaitAsync();
    Console.WriteLine($"{name} has access to the database");
    await Task.Delay(TimeSpan.FromSeconds(seconds));
    Console.WriteLine($"{name} is done with the database");
    semaphore.Release();
}

Task task1 = AccessDatabase("Task 1", 2);
Task task2 = AccessDatabase("Task 2", 2);

await Task.WhenAll(task1, task2);

Bu örnekte, “Task 1” ve “Task 2” adlı iki işlem, veritabanına erişmeye çalışıyor. Task.WhenAll metodu, her iki işlemin tamamlanmasını bekler.

Task.WaitAll ile Kullanımı

Task.WaitAll metodu, Task.WhenAll metodu gibi çalışır, ancak Task.WaitAll metodu, tüm Task‘ların tamamlanmasını bloklayarak bekler. Aşağıda bir örneğini görebilirsiniz:

SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);

void AccessDatabase(string name, int seconds)
{
    Console.WriteLine($"{name} is requesting access to the database");
    semaphore.Wait();
    Console.WriteLine($"{name} has access to the database");
    Thread.Sleep(TimeSpan.FromSeconds(seconds));
    Console.WriteLine($"{name} is done with the database");
    semaphore.Release();
}

Task task1 = Task.Run(() => AccessDatabase("Task 1", 2));
Task task2 = Task.Run(() => AccessDatabase("Task 2", 2));

Task.WaitAll(task1, task2);

Bu örnekte, “Task 1” ve “Task 2” adlı iki işlem, veritabanına erişmeye çalışıyor. Task.WaitAll metodu, her iki işlemin tamamlanmasını bekler.

Bu iki metodu kullanarak, birden fazla işlemi senkronize edebilir ve bir SemaphoreSlim ile kaynak erişimini kontrol edebilirsiniz.

Sonuç olarak, SemaphoreSlim, çok threadli bir uygulamada aynı anda yalnızca belirli sayıda threadin bir kaynağı kullanmasını sağlar. Bu, özellikle aynı anda birden fazla threadin aynı kaynağı kullanamayacağı durumlarda önemlidir, aksi takdirde çakışmalar olabilir. Ölü kilidi önlemek ve kaynak erişimini yönetmek için SemaphoreSlim‘i kullanabiliriz.



Bu gibi daha fazla gönderi...

Basit Bir Rest Api Client Geliştirelim 9

2023-05-14 | #diy-rest-api-client #do-it-yourself #net #rest-api

HTTP isteklerini izlemek ve teşhis etmek için daha fazla yetenek ekleyerek, kütüphanemizi daha da geliştirebiliriz. Bu amaçla, isteklerin ve yanıtların bazı temel bilgilerini loga kaydeden bir middleware ekleyelim. Bu özellik, HTTP isteklerinin ve yanıtlarının kaydını tutmak için HttpClient‘in DelegatingHandler sınıfını kullanır. Bu, bir HTTP isteği gönderildiğinde ve bir yanıt alındığında çalışan bir kod parçasıdır. Bu durumda, HTTP isteklerinin ve yanıtlarının bazı temel bilgilerini loga kaydeder. Aşağıda, bu özelliği eklemek için gereken kod parçacığı bulunmaktadır:

Devamı 


Basit Bir Rest Api Client Geliştirelim 8

2023-05-12 | #diy-rest-api-client #do-it-yourself #net #rest-api

Bu noktada, geliştirmemiz gereken bir diğer önemli konu da güvenlikle ilgili olabilir. Özellikle, API çağrıları genellikle belirli bir kimlik doğrulama yöntemi gerektirir. Bunu sağlamak için, HTTP istemcimizi çok kullanılan iki kimlik doğrulama yöntemiyle, yani Basic Authentication ve Bearer (Token) Authentication ile uyumlu hale getirebiliriz. Bu amaçla, istemcimize iki yeni metot ekleyelim: public void SetBasicAuthentication(string username, string password) { var basicAuthValue = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}")); SetDefaultHeader("Authorization", $"Basic {basicAuthValue}"); } public void SetBearerToken(string token) { SetDefaultHeader("Authorization", $"Bearer {token}"); } Bu metodlar, Authorization başlığını ayarlar, böylece her HTTP talebi kimlik doğrulama bilgilerini içerir.

Devamı 


Basit Bir Rest Api Client Geliştirelim 7

2023-05-12 | #diy-rest-api-client #do-it-yourself #net #rest-api

Birkaç özelleştirilebilir başlık ayarlama yeteneği ekleyelim. Bu özellik, belirli bir istek için özel HTTP başlıkları ayarlamayı kolaylaştıracaktır. using Newtonsoft.Json; using Polly; using Polly.Caching; using Polly.Caching.Memory; using Polly.Registry; using System; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; public class MyHttpClient : IDisposable { private readonly HttpClient _client; private readonly IPolicyRegistry<string> _policyRegistry; private readonly ILogger<MyHttpClient> _logger; public MyHttpClient(HttpClient client, IPolicyRegistry<string> policyRegistry, ILogger<MyHttpClient> logger, string baseAddress, TimeSpan? timeout = null, HttpMessageHandler handler = null) { _client = handler == null ?

Devamı 