Объект синхронизации Semaphore отличается от сигнальных событий наличием внутреннего счетчика с устанавливаемым максимальным значением. Объект AutoResetEvent можно интерпретировать как семафор с максимальным счетчиком равным 1 (двоичный семафор).
В следующем фрагменте рассматривается применение семафоров. В коде используется объект SemaphoreSlim. Вместо него можно использовать объект Semaphore.
// Применение семафоров class SemaphoreSlimTesting { private static SemaphoreSlim sem; private static void Worker(object num) { // Ждем сигнала от управляющего sem.Wait(); // Начинаем работу Console.WriteLine("Worker {0} starting", num); } private static void Main() { // Максимальная емкость семафора: 5 // Начальное состояние: 0 (все блокируются) sem = new SemaphoreSlim(0, 5); Thread[] workers = new Thread[10]; for(int i=0; i<workers.Length; i++) { workers[i] = new Thread(Worker); workers[i].Start(i); } Thread.Sleep(300); Console.WriteLine("Разрешаем работу трем рабочим"); sem.Release(3); Thread.Sleep(200); Console.WriteLine("Разрешаем работу еще двум рабочим"); sem.Release(2); } }
В методе Main инициализируется семафор SemaphoreSlim. Начальное значение внутреннего счетчика равно 0, максимальное значение – 5. Рабочие потоки блокируются, так как счетчик семафора равен нулю. Главный поток увеличивает счетчик на три единицы, тем самым освобождая три потока. После небольшой паузы главный поток освобождает еще два потока.
Вывод программы:
Разрешаем работу трем рабочим
Worker 9 starting
Worker 6 starting
Worker 0 starting
Разрешаем работу еще двум рабочим
Worker 8 starting
Worker 1 starting