Utilice la clase Semaphore para controlar el acceso a un grupo de recursos. Para entrar en el semáforo, los subprocesos llaman al método WaitOne, que se hereda de la clase WaitHandle, y para liberarlo llaman al método Release.
El recuento de un semáforo disminuye cada vez que un subproceso entra en él, e incrementa cuando un subproceso lo libera. Cuando el recuento es cero, las solicitudes posteriores se bloquean hasta que otros subprocesos liberan el semáforo. Cuando todos los subprocesos han liberado el semáforo, el recuento está en el valor máximo especificado al crear el semáforo.
No hay ningún orden garantizado, como FIFO o LIFO, para la entrada de los subprocesos bloqueados en el semáforo.
Un subproceso puede entrar varias veces en el semáforo, mediante llamadas al método WaitOne. Para liberar algunas de estas entradas o todas ellas, el subproceso puede llamar varias veces a la sobrecarga del método Release sin parámetros, o bien a la sobrecarga del método Release(Int32), que especifica el número de entradas que se liberan.
La clase Semaphore no exige la identidad del subproceso en las llamadas a WaitOne o Release. Es responsabilidad del programador garantizar que los subprocesos no liberen el semáforo demasiadas veces. Por ejemplo, supongamos que un semáforo tiene un recuento máximo de dos y que entran en el semáforo los subprocesos A y B. Si un error de programación del subproceso B hace que llame a Release dos veces, las dos llamadas tienen éxito. Se alcanza el recuento máximo del semáforo y, si el subproceso A llama posteriormente a Release, se genera una excepción SemaphoreFullException.
Los semáforos son de dos tipos: semáforos locales y semáforos de sistema con nombre. Si crea un objeto Semaphore mediante un constructor que acepta un nombre, se asocia a un semáforo del sistema operativo con ese nombre. Los semáforos de sistema con nombre son visibles en todo el sistema operativo y se pueden utilizar para sincronizar las actividades de los procesos. Puede crear varios objetos Semaphore que representan el mismo semáforo de sistema con nombre y, para abrir un semáforo de sistema con nombre ya existente, puede utilizar el método OpenExisting.
Un semáforo local sólo existe dentro del proceso. Puede utilizarlo cualquier subproceso del proceso que contenga una referencia al objeto Semaphore local. Cada objeto Semaphore es un semáforo local distinto.