Рассмотрим
var semaphore = new SemaphoreSlim(2);
Это означает, что семафор в данный момент имеет только 2 слота выполнения, но вы должны иметь в виду, что это только начальное число слоты для выполнения (для одновременных запросов).
Итак, если мы создадим поток A, B, C в семафор с двумя слотами для выполнения, первые два потока будут выполнены, а поток C будет поставлен в очередьпока кто-то еще в коде не сообщит семафору, что это нормально, чтобы добавить еще один слот выполнения.
Когда кто-то скажет, что все в порядке, чтобы выполнить следующий поток в очереди, C будет выполняться независимо от другихthread.
Несколько технических примеров:
(как я видел в курсе @ dmitri-nesteruk)
Общее количество доступных казнейslots представляется как CurrentCount
.
Каждый раз, когда поток хочет исполниться, он спрашивает семафор, есть ли у него доступный слот выполнения (с CurrentCount > 0
), если true - не стесняйтесь получитьВыполните сами, если не попадете в очередь.
Что делает семафор настолько запутанным, так это то, что значение CurrentCount
может быть уменьшено или увеличено.
Его значение уменьшается на единицу каждый раз, когда потоком вызывается Wait()
, что означает, что имеется один менее доступный слот выполнения и выполняется поток.
Увеличивается на единицу (или более) каждый раз, когда Release(1)
вызывается где-то еще в коде, что означает, что есть еще один доступный слот выполнения, поэтому первый поток внутри семафора внутри очередь выполняется (остальные не прекратятся).
В этом примере мы порождаем 3 потока, но только первые два будут выполняться докто-то скажет семафору, что он может освободить другой слот выполнения, увеличив CurrentCount
на Release(1)
.
for (int i = 0; i < 3 ; i++)
{
Task.Factory.StartNew(() =>
{
Console.WriteLine($"Spawning task: {Task.CurrentId}");
semaphore.Wait(); //CurrentCount--
Console.WriteLine($"Executing task: {Task.CurrentId}");
});
}
while (semaphore.CurrentCount <= 2)
{
Console.ReadKey();
Console.WriteLine("Key pressed");
semaphore.Release(1); //CurrentCount++
}
Выход:
Spawning task: A
Spawning task: B
Spawning task: C
Executing task: A
Executing task: B
.....
Key pressed
Executing task: C