AnDi_P Geschrieben 7. Mai 2010 Geschrieben 7. Mai 2010 (bearbeitet) Hallo zusammen ich bin gerade dabei eine kleine Anwendung in C# zu erstellen, die in einer Samba-Freigabe 12 gemountete Daten-Server rekursiv nach Verzeichnissen durchsucht, in dessen Name sich ein bestimmter String befinden muss. Da dieses recht viele Verzeichnisse (in mehreren Ebenen) sind, führt da kein Weg an Multithreading vorbei. Ich habe mir dazu unten aufgeführte Methode erstellt, die mit mehreren Threads (einstellbar) die Server durchsuchen soll. Erklärung dazu, wie es funktioniert: Ich starte zuerst einen Überwachungs-Thread, der eine Liste aller in der Freigabe verfügbaren Server in einem string-Array speichert, sowie danach ein boolean-Array, passend zu der Anzahl der Server. Gleichzeitig wird eine "Loading" Message im GUI angezeigt. Dann durchläuft jeder gestartete Such-Thread das boolean-Array, um zu gucken, bei welchem Filer ein "false" (für nicht durchsucht) steht. Wenn dem so ist, wird dieser Filer auf "true" gesetzt, und durchsucht. Somit soll dann das doppelte durchsuchen verhindert werden. Wenn ein Thread fertig ist, wird eine Variable für die Anzahl laufender Threads heruntergezählt. Derweilen guckt der Überwachungs-Thread permanent, wieviele Threads noch laufen (anhand der Zähler-Variable). Wenn der Wert bei 0 liegt, wird die "Loading" Message im GUI entfernt. Mit 4 Such-Threads + Überwachungs-Thread gab es bei mir die beste Geschwindigkeit (Core2Duo 2,8 GHz). public static void SearchOrderPaths(string Kdnr, int amountOfThreads) { int runningThreads = amountOfThreads; Thread searchPaths = new Thread(delegate() // Überwachtungs-Thread { SetWaitText("directory", true); // Event: Wartetext anzeigen DateTime start = DateTime.Now; // Zeitmessung starten string[] strFiler = Directory.GetDirectories(UncPathToShare); // Ermittlung der Filer in der Freigabe bool[] boolFilerChecked = new bool[strFiler.Length]; // boolean für jeden Filer, ob bereits überprüft for(int i = 0; i < amountOfThreads; i++) // parallele Suchthreads starten { Thread searchInstance = new Thread(delegate() { for (int filernr = 0; filernr < strFiler.Length; filernr++) { if (boolFilerChecked[filernr] == false) { try { boolFilerChecked[filernr] = true; foreach (string subdirectory in Directory.GetDirectories(strFiler[filernr] + @"\taschenbatcher\", "*", SearchOption.AllDirectories)) { logger.Info(Thread.CurrentThread.ManagedThreadId + " Filernr:" + filernr + " " + subdirectory); ; if (!applicationTerminated) // Prüfen ob Anwendung geschlossen { if(subdirectory.Contains(Kdnr)) AddPathItems(subdirectory); } else Thread.CurrentThread.Abort(); } } catch (DirectoryNotFoundException ex) { logger.Error(ex.Message); continue; }; } } runningThreads -= 1; // Wenn Thread beendet wird }); searchInstance.Start(); } while (applicationTerminated == false) // Prüfen ob Anwendung geschlossen { if (runningThreads == 0) // Prüft wieviele Threads laufen { DateTime end = DateTime.Now; TimeSpan neededtime = end - start; logger.Info(neededtime); // Benötigte Zeit in Logdatei schreiben SetWaitText("directory", false); break; } } }); searchPaths.Start(); // Starten des Threads } Jetzt ist meine Frage, ob man hier noch Optimierungen vornehmen kann, um die Suche zu beschleunigen. Derweil braucht man für das komplette durchsuchen minimum 1:20 min - was allerdings auch von den anderen Belastungen auf den Filern abhängt. Bin leider noch eher Anfänger, was programmieren & Multithreading angeht. Ich vermute auch, dass dieses eine ziemlich unsaubere Lösung ist - mir ist allerdings nicht's gescheiteres eingefallen. Auch google hat mir für meine Idee nicht's wirklich passendes angeboten. Wäre nett, wenn sich das vielleicht mal jemand anschauen könnte. Vielen Dank im Vorraus! MfG AnDi_P Bearbeitet 7. Mai 2010 von AnDi_P Zitieren
El Ninjo Geschrieben 7. Mai 2010 Geschrieben 7. Mai 2010 Es ist vllt einfacher mit dem ThreadPool zu arbeiten, anstatt explizit Thread-Objekte zu nutzen. Ansonsten verweise ich auf folgenden Artikel aus dem MSDN Magazine der sich ziemlich detailliert mit Multithreading in .NET auseinandersetzt und diehäufigsten Probleme/Gefahren (Deadlocks, Races etc.) und deren Lösungen (Sperren, Synchronisation...) vorstellt. LG Zitieren
AnDi_P Geschrieben 8. Mai 2010 Autor Geschrieben 8. Mai 2010 Schonmal danke für deine Antwort! Werde ich mir mal anschauen. Aber ist es denn auch performanter mit der ThreadPool-Klasse zu arbeiten, oder vereinfacht dies eher nur das Management/Überwachung der einzelnen Threads? LG Zitieren
El Ninjo Geschrieben 10. Mai 2010 Geschrieben 10. Mai 2010 Aber ist es denn auch performanter mit der ThreadPool-Klasse zu arbeiten ThreadPool-Threads sind Bestandteile der Laufzeitumgebung und somit schon für bestmögliche Performance optimiert. Ein interessanter Artikel dazu ist das hier: Pedram Rezaei's Ramblings : Dedicated thread or a Threadpool thread? Jede BeginInvoke-Anweisung nutzt z.B. auch den ThreadPool. oder vereinfacht dies eher nur das Management/Überwachung der einzelnen Threads? Meiner Meinung nach wird der Code zumindest übersichtlicher/einfacher zu lesen... Zitieren
AnDi_P Geschrieben 11. Mai 2010 Autor Geschrieben 11. Mai 2010 (bearbeitet) Habe nun mal, nach dem lesen des Artikels, mein Programm von dedizierten Such-Threads auf die ThreadPool-Klasse umgebaut. Fazit: Die Suche dauert zwar nun minimal länger, aber dafür ist die CPU-Auslastung auch drastisch gesunken! Vielen Dank für die Tipps MfG Andi_P Bearbeitet 11. Mai 2010 von AnDi_P Zitieren
AmunRa Geschrieben 14. Mai 2010 Geschrieben 14. Mai 2010 Zum Thema Multithreading in C# ist der folgende Artikel sehr interessant. Multithreading in C# Dort werden auch Threadpools erklärt. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.