Hier ist der Code, den ich habe, aber ich verstehe nicht, was er SemaphoreSlim
tut.
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
}
}
Was erwartet ss.WaitAsync();
und ss.Release();
tut?
Ich denke, wenn ich 50 Threads gleichzeitig laufen lasse und dann Code schreibe SemaphoreSlim ss = new SemaphoreSlim(10);
, wird er gezwungen sein, 10 aktive Threads gleichzeitig auszuführen.
Wenn einer von 10 Threads abgeschlossen ist, wird ein anderer Thread gestartet. Wenn ich nicht richtig liege, helfen Sie mir, die Beispielsituation zu verstehen.
Warum wird await
zusammen mit benötigt ss.WaitAsync();
? Was macht ss.WaitAsync();
das
Antworten:
Das ist richtig; Durch die Verwendung des Semaphors wird sichergestellt, dass nicht mehr als 10 Mitarbeiter gleichzeitig diese Arbeit ausführen.
Das Aufrufen
WaitAsync
des Semaphors erzeugt eine Aufgabe, die abgeschlossen wird, wenn diesem Thread "Zugriff" auf dieses Token gewährt wurde.await
Wenn Sie diese Aufgabe ausführen, kann das Programm die Ausführung fortsetzen, wenn dies "erlaubt" ist. EsWait
ist wichtig, eine asynchrone Version zu haben, anstatt sie aufzurufen , um sicherzustellen, dass die Methode asynchron bleibt und nicht synchron ist, undasync
um zu berücksichtigen , dass eine Methode aufgrund der Rückrufe Code über mehrere Threads hinweg ausführen kann Die natürliche Fadenaffinität zu Semaphoren kann ein Problem sein.Eine Randnotiz:
DoPollingThenWorkAsync
sollte dasAsync
Postfix nicht haben, da es nicht wirklich asynchron ist, sondern synchron. Nenn es einfachDoPollingThenWork
. Dies wird die Verwirrung der Leser verringern.quelle
Thread.Sleep
im ursprünglichen Code würde den Taskplaner zerstören. Wenn Sie nicht asynchron zum Kern sind, sind Sie nicht asynchron.Im Kindergarten um die Ecke steuern sie mit einem SemaphoreSlim, wie viele Kinder im Sportraum spielen können.
Sie malten auf dem Boden außerhalb des Raumes 5 Paar Fußabdrücke.
Als die Kinder ankommen, lassen sie ihre Schuhe auf einem freien Paar Fußabdrücke und betreten den Raum.
Sobald sie mit dem Spielen fertig sind, kommen sie heraus, sammeln ihre Schuhe und "geben" einen Platz für ein anderes Kind frei.
Wenn ein Kind ankommt und keine Fußspuren mehr vorhanden sind, spielen sie woanders oder bleiben nur eine Weile in der Nähe und überprüfen ab und zu (dh keine FIFO-Prioritäten).
Wenn eine Lehrerin in der Nähe ist, "gibt" sie eine zusätzliche Reihe von 5 Fußabdrücken auf der anderen Seite des Korridors frei, sodass 5 weitere Kinder gleichzeitig im Raum spielen können.
Es hat auch die gleichen "Fallstricke" von SemaphoreSlim ...
Wenn ein Kind mit dem Spielen fertig ist und den Raum verlässt, ohne die Schuhe einzusammeln (löst nicht die "Freigabe" aus), bleibt der Steckplatz blockiert, obwohl theoretisch ein leerer Steckplatz vorhanden ist. Das Kind wird jedoch normalerweise abgesagt.
Manchmal verstecken ein oder zwei hinterhältige Kinder ihre Schuhe woanders und betreten den Raum, selbst wenn alle Fußabdrücke bereits aufgenommen wurden (dh der SemaphoreSlim kontrolliert nicht "wirklich", wie viele Kinder sich im Raum befinden).
Dies endet normalerweise nicht gut, da die Überfüllung des Raums dazu führt, dass Kinder weinen und der Lehrer den Raum vollständig schließt.
quelle
Obwohl ich akzeptiere, dass sich diese Frage wirklich auf ein Countdown-Sperrszenario bezieht, hielt ich es für sinnvoll, diesen Link zu teilen, den ich für diejenigen entdeckt habe, die einen SemaphoreSlim als einfache asynchrone Sperre verwenden möchten. Sie können die using-Anweisung verwenden, die die Codierung übersichtlicher und sicherer machen könnte.
http://www.tomdupont.net/2016/03/how-to-release-semaphore-with-using.html
Ich habe Swap
_isDisposed=true
und_semaphore.Release()
um in seiner Entsorgen obwohl im Fall irgendwie ist es mehrmals aufgerufen wurde.Es ist auch wichtig zu beachten, dass SemaphoreSlim keine Wiedereintrittssperre ist. Wenn also derselbe Thread WaitAsync mehrmals aufruft, wird die Anzahl der Semaphore jedes Mal dekrementiert. Kurz gesagt, SemaphoreSlim ist nicht Thread-fähig.
In Bezug auf die Fragen in Bezug auf die Codequalität ist es besser, die Veröffentlichung innerhalb eines endgültigen Versuchs zu platzieren, um sicherzustellen, dass sie immer veröffentlicht wird.
quelle