2010-03-22 6 views
7

Ich habe diese Anwendung, die alle Ordner in einem bestimmten Verzeichnis recurse und nach PDF suchen. Wenn eine PDF-Datei gefunden wird, zählt die Anwendung ihre Seiten mit ITextSharp. Ich tat dies, indem ich einen Thread benutzte, um alle Ordner für pdf rekursiv zu scannen, und wenn dann PDF gefunden wird, wird es in den Thread-Pool eingereiht. Der Code sieht wie folgt aus:Wie kann man wissen, ob der gesamte Thread-Pool-Thread bereits mit seinen Aufgaben erledigt ist?

//spawn a thread to handle the processing of pdf on each folder. 
       var th = new Thread(() => 
       { 
        pdfDirectories = Directory.GetDirectories(pdfPath); 
        processDir(pdfDirectories); 
       }); 
       th.Start(); 



private void processDir(string[] dirs) 
     { 
      foreach (var dir in dirs) 
      { 
       pdfFiles = Directory.GetFiles(dir, "*.pdf"); 
       processFiles(pdfFiles); 

       string[] newdir = Directory.GetDirectories(dir); 
       processDir(newdir); 
      } 
     } 



private void processFiles(string[] files) 
     { 
      foreach (var pdf in files) 
      { 
       ThreadPoolHelper.QueueUserWorkItem(
        new { path = pdf }, 
        (data) => { processPDF(data.path); } 
        ); 
      } 
     } 

Mein Problem ist, wie kann ich wissen, dass der Thread des Thread-Pool hat alle Warteschlange Elemente beendet die Verarbeitung, so dass ich den Benutzer sagen kann, dass die Anwendung mit ihrer beabsichtigten Aufgabe erledigt ist?

Antwort

4

Im Allgemeinen würde ich so etwas tun, indem ich eine Zählervariable habe. Fügen Sie für jedes Arbeitselement, das Sie in die Warteschlange einreihen, einen Wert ThreadPool zur Zählervariable hinzu. Dann, wenn es verarbeitet wird, würden Sie die Zählervariable verringern.

Stellen Sie sicher, dass Sie das Inkrementieren und Dekrementieren über die Methoden der Klasse Interlocked durchführen, da dies sicherstellt, dass Dinge auf thread-sichere Weise ausgeführt werden.

Sobald die Zähler Hits Null Sie Flag könnte, dass die Aufgaben abgeschlossen sind eine ManualResetEvent

Verwendung Wenn Sie Zugriff auf .NET 4 haben, dann können Sie die neue CountdownEvent Klasse verwenden, um eine ähnliche Sache zu tun.

+0

Ich habe eine ähnliche Logik zu diesem Thema gemacht. Nur ich habe die ThreadPool.GetAvailableThreads verwendet. Ich setzte die MaxThreads, die die Pools verwenden sollten, mit 20. Also habe ich bei der letzten Aufgabe überprüft, ob die verfügbaren Threads gleich dem Max sind, den ich gesetzt habe. Leider schlägt das fehl. Ich werde über das Manual Reset Event nachforschen. –

+1

@mcxiand: Sie können die ThreadPool-Leistungsindikatoren nicht verwenden, da anderer Code (lib) Threads erstellen könnte und der TP sie recycelt/löscht. –

+0

@Henk Holterman: Ist das so? Von dem, was ich verstanden habe, ist der ThreadPool Task von QueueUserWorkItem-Methode in die Warteschlange gestellt. Kannst du mehr Details zu deinem Kommentar angeben? es würde sehr geschätzt werden. –

2

1) Wie kann man wissen, ob alle Threads beendet sind?

Sie werden die Themen zu tun, ihre eigene Check-in/Check-out lassen müssen, indem Sie den Code zwischen Bracketing:

Interlocked.Increment(ref jobCounter); 
// your code 
Interlocked.Decrement(ref jobCounter); 

Wenn dies zu Ihren anonym Delegierten vermasselt viel verwenden Sie dann nur Wrapper-Methoden. Wahrscheinlich müssen Sie auch die Ausnahmebehandlung hinzufügen.

Der verzahnte Ansatz trotzt immer noch dem Problem, auf 0 zu warten, eine Schleife mit Sleep() ist eine schwache, aber in diesem Fall praktikable Lösung.

2) Sie starten Threads in einem rekursiven Tree Walker. Sei vorsichtig, du schaffst wahrscheinlich zu viel von ihnen und das wird die Leistung beeinträchtigen.

+0

Ich habe nur einen Thread, um die rekursive und Warteschlange jedes PDF-Dateien in jedem Ordner durch den Thread –

+0

OK, es ist mehr linear. Und von den Kommentaren drosselt man MaxThreads. Immer noch Tuning und Ändern MaxThreads ist ein Vorschlaghammer. –

+0

Ich habe die MaxThreads gesteuert, weil ich in diesem Thread die UI-Steuerung mit BeginInvoke aktualisiere. Die Benutzeroberfläche wird eingefroren, wenn viele Threads ausgeführt werden. Irgendwelche Empfehlungen? –

Verwandte Themen