Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
StackOverflowException beim rekursiven Verarbeiten von Verzeichnissen mittels Queue
DMsRising
myCSharp.de - Member



Dabei seit:
Beiträge: 4
Herkunft: Deutschland

Themenstarter:

StackOverflowException beim rekursiven Verarbeiten von Verzeichnissen mittels Queue

beantworten | zitieren | melden

Guten Abend,
ich hoffe ich finde in diesem Forum Hilfe: Und zwar rufe ich einen einen Pfad und alle Unterordner rekursiv auf, um alle in den Odernern und Unterordnern Gefundenen Dateien in eine Liste zu packen. Sobald allerdings eine Verknüpfung oder ein vom System geschützer Ordner an der Reihe ist, bricht das Programm mit einer Stackoverflowexception ab.


 private void DataNamesToList()
        {
            _di = new DirectoryInfo(_pathQueue.Dequeue()); //Setzte aktuelles verzeichnis aus queue
            try
            {
                foreach (FileInfo f in _di.GetFiles())  // ≤= HIER
                {
                    _dateiNamen.Add(f.Name); //füge alle Dateien des Ordners an Liste an
                }
            }
            catch (Exception ex)//wird beim stackoverflow leider nicht abgefangen
            {
                
            }
            if (checkBox_unterordner.Checked) 
            {
                foreach (DirectoryInfo d in _di.GetDirectories()) //füge rekursiv alle unterordner und
                {                                                                   //deren unterordner in die queue
                    _pathQueue.Enqueue(d.FullName);
                }
                if (_pathQueue.Count > 0)
                    DataNamesToList();
            }
        }

Bei Rot markierter Stelle findet sich immer wieder die Meldung
Fehler
Eine nicht behandelte Ausnahme des Typs "System.StackOverflowException" ist in mscorlib.dll aufgetreten.
Unter Details findet sich folgendes:
Fehler
Ausnahme-Momentaufnahme:
-> System.StackOverflowException {Der Ausdruck kann nicht ausgewertet werden, weil sich der aktuelle Thread in einem Stapelüberlaufzustand befindet.}

Gibt es dazu bereits einen Thread, der dieses Problem behandelt und den ich überlsesen habe, oder kann mir zeigen, wie ich die SOE abfangen, bzw. Systemordner und Verküpfungen von der Suche ausschließen kann?

Viele Grüße
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

beantworten | zitieren | melden

Hallo,

du kannst eine SOE nicht abfangen, weil dein Stack halt zu voll ist um noch irgendwas zu machen.

Zu deiner Logik.. Für mich vermischt Du hier zwei verschiedene Methoden an das Problem heran zu gehen. Einmal die Rekursion und einmal Abarbeitung mit einer Queue. Die Queue ist hier denke ich über.


private void DataNamesToList(DirectoryInfo di)
        {
           
            try
            {
               foreach (FileInfo f in _di.GetFiles())
                {
                    _dateiNamen.Add(f.Name); //füge alle Dateien des Ordners an Liste an
                }
            }
            catch (Exception ex)//wird beim stackoverflow leider nicht abgefangen
            {
                //Und hier solltest Du die Exception behandeln!


            }
            if (checkBox_unterordner.Checked)
            {
                foreach (DirectoryInfo d in _di.GetDirectories()) //füge rekursiv alle unterordner und
                {                                                                   //deren unterordner in die queue
                   DataNamesToList(d);
                }
               
                    
            }
        }

allerdings ist mir bis jetzt entgangen warum Du eine SOE bekommst..
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von unconnected am .
private Nachricht | Beiträge des Benutzers
LittleBoy
myCSharp.de - Member



Dabei seit:
Beiträge: 55

beantworten | zitieren | melden

Moderationshinweis von herbivore (13.10.2014 - 21:11:43):

Um es vorweg zu nehmen: GetDirectories liefert nur Unterverzeichnisse. Und GetDirectories mit SearchOption.AllDirectories scheitert, wenn auch nur auf ein Verzeichnis keine Zugriffsrechte bestehen. Das gleiche gilt für EnumerateDirectories, zumindest wenn bis zum Verzeichnis mit den fehlenden Zugriffsrechten enumeriert wird.


Hi,

ohne jetzt genau in die Doku geschaut zu haben: Möglicherweise liefert GetDirectories() das aktuelle bzw. das übergeordnete Verzeichnis zurück ("." und "..") - das würde dann den Stacküberlauf erklären.

Unabhängig davon ist die Rekursion hier doch gar nicht notwendig, denn eine Überladung von GetDirectories() kann auch direkt alle Unter-Unterverzeichnisse zurückliefern.

Zuguterletzt würde ich ggf. auf die aktuelleren Versionen EnumerateDirectories zurückgreifen.


Und um noch auf die eigentliche Frage einzugehen: Eine StackOverflow-Exception ist so "schlimm", dass man sie nicht fangen kann. (bzw. nur unter ganz bestimmten Umständen)

Gruß,
Sebastian
private Nachricht | Beiträge des Benutzers
DMsRising
myCSharp.de - Member



Dabei seit:
Beiträge: 4
Herkunft: Deutschland

Themenstarter:

beantworten | zitieren | melden

warum ist die queue für dich überflüssig?
die benutz ich, um mir die neu auftauchenden Unterordnerpfade zu speichern und systematisch alle aufzunehmen und abzuarbeiten.
@LittelBoy
GetDirectories() wird nicht daran Schuld sein. Wenn ich unterordner aktiviere und ein Verzeichnis ohne Systemordner/verknüpfungen lese, bekomm ich keinen Stackoverflow.

Was genau meinst du mit 'aktuelleren Versionen EnumerateDirectories' ?
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo DMsRising,

deine Verbindung von Rekursion und Queue ist wirklich sehr ungünstig. So wie es jetzt ist, entspricht die Rekursionstiefe der Anzahl der insgesamt gefundenen Verzeichnisse und nicht wie üblich (z.B. in [Snippet] Verzeichnisse und Dateien rekursiv durchlaufen) der Verschachtelungstiefe der Verzeichnisse.

Verwende statt der Rekursion eine Schleife. Dann bist du die SOE los.

EnumerateDirectories ist eine neue Methode, die aber nur dann spürbare Vorteile bringt, wenn man vor hat, die Enumeration abzubrechen, bevor alle Verzeichnisse durchlaufen sind (hast du nicht vor). Oder wenn man Verzeichnisse mit extrem vielen Unterverzeichnissen hat (keine Ahnung ob das bei dir denkbar ist). Ansonsten kann man weiterhin GetDirectories verwenden. GetDirectories hat aus meiner Sicht den Vorteil, dass es das komplette Ergebnis liefert oder gar keins (SecurityException). Bei EnumerateDirectories können Exceptions mitten in der Enumeration auftreten. Und GetDirectories ist sowieso angezeigt, wenn man die Verzeichnisse vor der Verarbeitung sortieren will oder muss. Es kommt also auf die konkrete Situation an, ob die eine oder die andere Methode besser geeignet ist.

Eine mögliche Exception bei GetDirectories solltest du behandeln, so wie du es bei GetFiles auch getan hast.

herbivore
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

beantworten | zitieren | melden

Ja, stimmt jetzt habe ich es auch.

Solange in der Queue noch was drin ist, wird die Methode pro Verzeichnis nochmals aufgerufen: Stack++

Und um nochmals zu Fragen: Was spricht dagegen die Queue raus zu schmeissen? Mir würde hier nur Multithreading einfallen, aber in diesem Fall fehlen noch Infos.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von unconnected am .
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo unconnected,

die Queue muss man nicht zwangsweise rausschmeißen. Es gibt eben die beiden Möglichkeiten. In einer Schleife eine Queue mit den Verzeichnissen zu füllen und sie abzuarbeiten. Oder die Verzeichnisstruktur rekursiv zu durchlaufen. Das hat beides seine Berechtigung. Keines davon ist ausschließlich besser oder ausschließlich schlechter als die jeweils andere Möglichkeit. DMsRising sollte sich nur klar für eines von beidem entscheiden. Der Mix ist es, der die Probleme verursacht.

Mit Rekursion bekommt man standardmäßig eine Tiefensuche. Mit einer Queue bekommt man standardmäßig eine Breitensuche.

herbivore
private Nachricht | Beiträge des Benutzers
user8744
myCSharp.de - Member



Dabei seit:
Beiträge: 1201

beantworten | zitieren | melden

Zitat
Sobald allerdings eine Verknüpfung oder ein vom System geschützer Ordner an der Reihe ist

Das mit der Verknüpfung kann ich nicht beurteilen aber ich würde mich wundern wenn System.File.IO ein .lnk automatisch verarbeitet. Ich will es aber auch nicht ausschliessen, obwohl ich mir doch recht sicher bin recht zu haben.

Der Zugriff auf einen Systemordner ist nicht anders als der Zugriff auf anderer Ordner ausser das man eine Security Exception erwarten muss(wie bei allen anderen Ordnern eigentlich auch)

Insofern ist deine Beobachtung und dein Folgeschluss falsch. Der System Ordner und wahrscheinlich auch die Verknüpfung hat nix damit zu tun das du eine SOE Exception bekommst. Du rufst in einem 2. Codeblock nach try/catch ja nochmal GetDirectory auf, warum und woher weisst du das die Exception nicht aus dem Codeblock stammt, speziell aus deinen eigenen Methoden pathQueue(was immer das ist) oder DataNamesToList . Dein try/catch block mit GetFiles() sollte aus meiner Sicht keine SOE Exception werfen ausser dein Dateisystem ist so überfüllt das er den zulässigen Stack Memory in .Net überschreitet. Anders gesagt ich habe nicht den Eindruck das die SOE Exception vom FileSystem kommt, jedenfalls sehe ich darauf keinen Hinweis.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo Sebastian.Lange,

richtig, Verknüpfungen im Sinne von LNK-Dateien auf Ordner wird nicht automatisch gefolgt. Die werden von GetFiles geliefert, nicht von GetDirectories. Aber es gibt andere Arten von Verknüpfungen, z.B. Hardlinks oder Junktions, die von GetDirectories geliefert werden, als wären sie normale Verzeichnisse. Siehe dazu auch die Diskussion in [Snippet] Verzeichnisse und Dateien rekursiv durchlaufen ff bis zum Beitrag von winSharp93 [Snippet] Verzeichnisse und Dateien rekursiv durchlaufen, der eine Lösungsmöglichkeit aufzeigt. Insofern könnte durch eine derartige Verknüpfung durchaus eine Endlosrekursion entstehen. Ich bin allerdings deiner Meinung, dass dies hier eher trotzdem nicht der Fall ist, sondern die Ursache in der Art der Rekursion liegt, die ich weiter oben beschrieben habe.

herbivore
private Nachricht | Beiträge des Benutzers