Zum Inhalt springen

Frage zu Threadoptimierung


AnDi_P

Empfohlene Beiträge

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 von AnDi_P
Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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...

Link zu diesem Kommentar
Auf anderen Seiten teilen

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 von AnDi_P
Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...