2012-04-16 6 views
14

Ich habe ein Visual Studio 2008 C# .NET 3.5-Projekt, wo eine Klasse auf einen Ereignisaufruf von einer anderen Klasse, die Multithread ist, wartet. Ich muss sicherstellen, dass mein Event nur den gleichzeitigen Zugriff auf maximal 10 Threads erlaubt. Der 11. Thread sollte blockieren bis einer der 10 endet.Eine Funktion, die nur N gleichzeitige Threads erlaubt

myobj.SomeEvent += OnSomeEvent; 

private void OnSomeEvent(object sender, MyEventArgs args) 
{ 
    // allow up to 10 threads simultaneous access. Block the 11th thread. 
    using (SomeThreadLock lock = new SomeThreadLock(10)) 
    {   
     DoUsefulThings(args.foo); 
    } 
} 

Ich habe keine Kontrolle über die andere MyObj Klasse, so kann ich eine Thread es nicht implementieren.

Was ist der beste Weg, dies zu implementieren?

Danke, PaulH

Antwort

21

Sie wollen die Semaphore class. Es ist, kurz gesagt, eine Sperre, die nur eine bestimmte Anzahl von Anrufern zu jeder Zeit durchlässt.

Da Sie die Erstellung von Threads nicht steuern, müssen Sie bei Deadlock-Situationen vorsichtig sein. Semaphore sind nicht reentrancy-aware - wenn ein bestimmter Thread mehr als einmal in einen Semaphor eintritt, benötigt er mehr als einen Slot. Wenn also jeder Thread Ihres Aufrufers mehr als einmal in Ihren Semaphor eindringt, besteht die Möglichkeit eines Deadlocks.

3

Es ist üblich, hierfür einen Semaphor zu verwenden. Initialisiere es auf 10 Einheiten. wait() für eine Einheit vor DoUsefulThings(), signal() danach eine Einheit.

9

Verwenden Sie hierfür eine Semaphore. Die Konstruktorparameter sind etwas verwirrend für diejenigen, die gerade in die Klasse eingeführt werden. Der erste Parameter gibt die anfängliche Anzahl von Threads an, die durch gerade zulässig sind. Der zweite Parameter gibt die maximale Anzahl von Threads an, die zu einem bestimmten Zeitpunkt zulässig sind.

myobj.SomeEvent += OnSomeEvent; 
Semaphore semaphore = new Semaphore(10, 10); 

private void OnSomeEvent(object sender, MyEventArgs args) 
{ 
    semaphore.WaitOne(); 
    try 
    { 
    DoUsefulThings(args.foo); 
    } 
    finally 
    { 
    semaphore.Release(); 
    } 
} 
+1

+1 für die Feststellung, dass Sie den Semaphor im 'finally'-Block eines try/catch beenden sollten. Dies ist wichtig - falls Ihr Code eine Ausnahme auslöst, möchten Sie sicherstellen, dass der Semaphor beendet wird. –

Verwandte Themen