Voici le code que j'ai mais je ne comprends pas ce que je SemaphoreSlim
fais.
async Task WorkerMainAsync()
{
SemaphoreSlim ss = new SemaphoreSlim(10);
List<Task> trackedTasks = new List<Task>();
while (DoMore())
{
await ss.WaitAsync();
trackedTasks.Add(Task.Run(() =>
{
DoPollingThenWorkAsync();
ss.Release();
}));
}
await Task.WhenAll(trackedTasks);
}
void DoPollingThenWorkAsync()
{
var msg = Poll();
if (msg != null)
{
Thread.Sleep(2000); // process the long running CPU-bound job
}
}
Qu'est-ce qui attend ss.WaitAsync();
et que ss.Release();
fait?
Je suppose que si j'exécute 50 threads à la fois, j'écris du code comme SemaphoreSlim ss = new SemaphoreSlim(10);
il sera alors obligé d'exécuter 10 threads actifs à la fois.
Lorsque l'un des 10 threads se termine, un autre thread démarre. Si je n'ai pas raison, aidez-moi à comprendre avec un exemple de situation.
Pourquoi est-il await
nécessaire avec ss.WaitAsync();
? Que fait ss.WaitAsync();
-on?
Réponses:
C'est correct; l'utilisation du sémaphore garantit qu'il n'y aura pas plus de 10 ouvriers effectuant ce travail en même temps.
L'appel
WaitAsync
sur le sémaphore produit une tâche qui sera achevée lorsque ce thread aura "accès" à ce jeton.await
-ing cette tâche permet au programme de continuer son exécution quand il est "autorisé" à le faire. Avoir une version asynchrone, plutôt que d'appelerWait
, est important à la fois pour s'assurer que la méthode reste asynchrone, plutôt que synchrone, ainsi que pour gérer le fait qu'uneasync
méthode peut exécuter du code sur plusieurs threads, en raison des rappels, etc. l'affinité naturelle du fil avec les sémaphores peut être un problème.Remarque:
DoPollingThenWorkAsync
ne devrait pas avoir leAsync
suffixe car il n'est pas réellement asynchrone, il est synchrone. Appelez çaDoPollingThenWork
. Cela réduira la confusion pour les lecteurs.la source
Thread.Sleep
dans le code d'origine dévasterait le planificateur de tâches. Si vous n'êtes pas asynchrone au cœur, vous n'êtes pas asynchrone.Dans la maternelle du coin, ils utilisent un SemaphoreSlim pour contrôler le nombre d'enfants qui peuvent jouer dans la salle de PE.
Ils ont peint sur le sol, à l'extérieur de la pièce, 5 paires d'empreintes de pas.
À l'arrivée des enfants, ils laissent leurs chaussures sur une paire d'empreintes libres et entrent dans la pièce.
Une fois qu'ils ont fini de jouer, ils sortent, récupèrent leurs chaussures et «libèrent» une place pour un autre enfant.
Si un enfant arrive et qu'il n'y a plus d'empreintes de pas, il va jouer ailleurs ou simplement rester un moment et vérifier de temps en temps (c'est-à-dire pas de priorités FIFO).
Lorsqu'un enseignant est là, elle «libère» une rangée supplémentaire de 5 empreintes de pas de l'autre côté du couloir de sorte que 5 autres enfants puissent jouer dans la pièce en même temps.
Il a aussi les mêmes «pièges» que SemaphoreSlim ...
Si un enfant finit de jouer et quitte la pièce sans ramasser les chaussures (ne déclenche pas le «release») alors la fente reste bloquée, même s'il y a théoriquement une fente vide. Cependant, l'enfant se fait généralement dire.
Parfois, un ou deux enfants sournois cachent leurs chaussures ailleurs et entrent dans la pièce, même si toutes les empreintes de pas sont déjà prises (c'est-à-dire que le SemaphoreSlim ne contrôle pas "vraiment" le nombre d'enfants dans la pièce).
Cela ne se termine généralement pas bien, car la surpopulation de la salle a tendance à se terminer par les pleurs des enfants et par le professeur qui ferme complètement la salle.
la source
Bien que j'accepte cette question se rapporte vraiment à un scénario de verrouillage de compte à rebours, j'ai pensé qu'il valait la peine de partager ce lien que j'ai découvert pour ceux qui souhaitent utiliser un SemaphoreSlim comme un simple verrou asynchrone. Il vous permet d'utiliser l'instruction using qui pourrait rendre le codage plus propre et plus sûr.
http://www.tomdupont.net/2016/03/how-to-release-semaphore-with-using.html
J'ai échangé
_isDisposed=true
et_semaphore.Release()
circulé dans son Dispose au cas où il serait appelé plusieurs fois.Il est également important de noter que SemaphoreSlim n'est pas un verrou réentrant, ce qui signifie que si le même thread appelle WaitAsync plusieurs fois, le nombre du sémaphore est décrémenté à chaque fois. En bref, SemaphoreSlim n'est pas compatible avec Thread.
En ce qui concerne les questions sur la qualité du code, il est préférable de placer la version dans le dernier essai pour s'assurer qu'elle est toujours publiée.
la source