2017-11-27 4 views
-1

Ich möchte alle gesperrten Threads freigeben, nachdem einer von ihnen übergeben wurde, und den Task abschließen. Lassen Sie mich einen Beispielcode über das, was ich machen möchte, veröffentlichen. Wichtig ist, dass sie alle zusammen passieren müssen, nachdem der erste Thread seinen Job beendet hat. Sie (Ruhe 99 Fäden) müssen so sein, dass sie nie abgeschlossen haben, nicht eins nach dem anderen.Alle gesperrten Threads freigeben

  Monitor.Enter(_lock);//imagine 100x threads hit this lock at same time. 
     //1 thread pass there 
     if (data == null) 
     { 
      data = GetData(); 
     } 

     Monitor.Exit(_locker);//one more thread allow after this code.And they all come one by one in order.In these point I want to release them all together. 

Ich habe versucht, eine Menge Klasse über wie Monitor-Threading, Mutex, Semaphore, ReadWriteLock, ManaualResetEvent etc., aber ich habe es nicht geschafft, dies zu tun, kommen sie alle eins nach dem anderen. Hast du das jemals getan? Oder hast du eine Ameisen Idee? Ich möchte nicht mehr Zeit damit verbringen.

Antwort

0

Dies könnte nicht der effizienteste Weg sein, aber es funktioniert:

static SemaphoreSlim semaphore = new SemaphoreSlim(1, 1); 
static CancellationTokenSource cts = new CancellationTokenSource(); 
static void CriticalSection() 
{ 
    if(!cts.Token.IsCancellationRequested) 
    { 
     try 
     { 
      semaphore.Wait(cts.Token); 
     } 
     catch (OperationCanceledException) { } 
    } 
    /* 
    Critical section here 
    */ 
    if(!cts.Token.IsCancellationRequested) 
     cts.Cancel(); 
} 

die SemaphoreSlim nur lassen 1 Thread den „kritischen Bereich“ laufen. Nachdem der erste Thread mit dem Abschnitt beendet ist, wird das Token gelöscht. Dies führt zu einer OperationCanceledException wie beschrieben here. Alle wartenden Threads werfen die Ausnahme aus, die in der "try catch-Anweisung" abgefangen wird, und führen dann den kritischen Abschnitt aus. Die erste "if-Anweisung" besteht darin, den Status des Tokens zu überprüfen, um das Warte- und Wurfmuster zu vermeiden, wenn es in der Vergangenheit abgebrochen wurde.

Der Performance-Hit ist das erste Mal, wenn Ihre Threads vom Warten "freigegeben" werden, da sie alle eine Ausnahme auslösen. Später werden sich die Auswirkungen nur auf die Prüfung des Löschungs-Tokens und die allgemeine Wartbarkeit des Codes auswirken.

+0

Dieser Code hat bei jedem Aufrufer den kritischen Abschnitt ausgeführt, nachdem der CTS abgebrochen wurde. – Servy

+0

@Servy ist das nicht genau das, wonach das OP gefragt hat? – Daneau

+0

Der Wert muss * genau einmal * erstellt werden. – Servy

-2
static SemaphoreSlim semaphore = new SemaphoreSlim(1); 

    static void Main(string[] args) 
    { 
     for (int i = 0; i < 10; i++) 
     { 
      Thread t = new Thread(LoadDataPart); 
      t.Name = (i + 1).ToString(); 
      t.Start(); 
     } 

     Console.Read(); 
    } 

    static void LoadDataPart() 
    { 


     Console.WriteLine("Before Wait {0}", Thread.CurrentThread.Name); 
     semaphore.Wait(); 
     Console.WriteLine("After Wait {0}", Thread.CurrentThread.Name); 
     Thread.Sleep(3000); 
     Console.WriteLine("Done {0}", Thread.CurrentThread.Name); 

     semaphore.Release(10);//this line must be changed,its allow too much thread coz its called 10 times! 

    } 

Ich kann verwalten, was ich so tun möchte. In diesem Codebeispiel warten 10 Threads auf hit. 9 von ihnen warteten auf andere. Wenn 1 Thread seinen Job erledigt, geht andere 9 nicht eins nach dem anderen zusammen. Um zu überprüfen, dass ich Thread Schlaf und alle Fäden in 6 Sekunden nicht in 30 Sekunden kompiliert. Jetzt kann ich meinen Code anpassen.

+0

Es gibt ein paar Fehler bei diesem Ansatz. Wenn Sie die genaue Anzahl der zu erwartenden Threads nicht kennen, wird der Semaphore.Release (x) den Teil "Müssen alle zusammen übergeben" Ihrer Frage nicht zulassen.In diesem Fall funktioniert es, weil Ihre Thread-Nummer niedrig ist und Sie genau die gleiche Anzahl wie Ihre Thread-Anzahl freigeben und weil der "kritische Abschnitt" nicht so lange dauert. Sie werden auch die Semaphorzahl oft erhöhen, wie in der Probe gezeigt. – Daneau

+0

@Daneau Ja, ich habe dieses Problem bemerkt. Vielleicht kann ich das irgendwie verwenden, aber es sieht nicht nach einer genauen Lösung aus. Ich denke, es gibt keinen gesunden Weg, das zu tun. – Math1

Verwandte Themen