Synchronisiertes Zugreifen bei SortedSet?

Java4life

Grünschnabel
Hi Leute,
ich wollte nur mal fragen,ob sowas hier in der Art möglich ist bzw. wie ich das richtig machen kann:

C#:
public void machen2()
        {
            // Hier Fehler!
            foreach (String site in hsetlinks)
             {
                    // nehme Set-Element 
                    sammeln(site);
             }
        }

        public void sammeln(string startseite)
        {
            webBrowser1.Navigate(startseite);
            foreach (HtmlElement ele in webBrowser1.Document.Links)
            {
                        //trage in Set ein
                        hsetlinks.Add(ele.GetAttribute("href"));  
            }
            machen2();
        }

Letztendlich soll das Programm von einer Seite alle Links parsen,in ein Set eintragen,dann Set auslesen und wieder von den Seiten alle Links parsen. (Ich weiß,dass noch Abbruchbedingungen eingefügt werden müssen - wegen Endlosschleife).

Aber,ich möchte erstmal das Set synchronisieren, da dieser Fehler kommt:
Die Auflistung wurde geändert, nachdem der Enumerator instantiiert wurde.

Weiß jemand zufällig,wie ich die relativ einfach synchronisieren kann?

Danke schon mal und ein schönes Wochenende.
 
Hallo,

Diese Fehlermeldung kommt immer dann wenn du mit einer foreach-Schleife auf eine Liste/Set zugreifst die sich dann ändert.
An deiner Stelle würde ich mir überlegen ob es umbedingt notwendig ist ein SortedSet zu verwenden. Wenn du eine List verwendest und immer hinten anhängst brauchst du deine foreach nur in eine for-Schleife ändern damits funktioniert.
Für SortedSets ist mir keine Lösung bekannt mit der dein Problem funktionieren würde, daher würde ich vorschlagen, dass, wenn du wirklich ein SortedSet brauchst, du zuerst alles in eine List lädst und wenn du mit dem parsen fertig bist die Daten in ein SortedSet verschiebst.
 
Ok Danke. Habe das jetzt mit einer for-Schleife realisiert. Das funktioniert alles super, nur habe ich ein unverständliches Problem:

C#:
        public void sammeln2(int deep)
        {
            for (int i = 0; i < list.Count; i++) 
            {
                MessageBox.Show("Ausgabe: " + list[i]);
                sammeln(list[i],deep);
            }
        }
Wenn ich das so lasse (mit MessageBox), dann funktioniert alles einwandfrei. Wenn ich die Box allerdings rausnehme,dann werden die Links falsch geparsed. Jetzt stehe ich ein wenig auf dem Schlauch an was das liegen kann. Ist die Methode sammeln2 (Schleife) vielleicht zu "schnell" für die Methode sammeln? Habe es schon mit Thread.sleep versucht,um die Zeit der Box zu emulieren,aber leider kein Erfolg. Wie immer Danke für die Hilfe!
 
Solange sammeln nicht asynchron läuft wartet sammeln2 sowieso bei jedem Schleifendurchlauf bis sammeln beendet ist -> hat nichts mit der Laufzeit zu tun.

Zeig bitte mal den vollständigen Code her, damit man herumprobieren kann.
 
Hallo Java4life.

im Grunde handelst du dir das gleiche Problem ein, wie bei der ersten Lösung: Du änderst in der Schleife die Schleifenparameter. Du bekommst zwar hier keine Fehlermeldung, aber ein entsprechend seltsames Verhalten.

Ich würde die Hauptschleife daher mit einer Kopie der Liste durchlaufen:
C#:
public void machen2()
{
    SortedList temp = (SortedList)hsetlinks.Clone();

    foreach (String site in temp)
    {
        sammeln(site);
    }
}

Wie bildest du eigentlich die hierarchische Struktur einer solchen Linksammlung ab?

Gruß
MCoder
 
Hallo,

Es ist ja gerade der Sinn der Sache die for-Schleife solange laufen zu lassen bis ALLE Elemente abgearbeitet sind. Wenn man hier eine Kopie verwendet würde man nur durch den Startzustand der Liste iterieren.
Und einer for-Schleife ist es, da die Bedingung nach jedem Durchlauf ausgewertet wird, egal ob man die Liste ändert.

Edit: Hab jetzt den Grund gefunden:
Das Problem liegt am
C#:
webBrowser1.Navigate(startseite);
. Das wird nämlich nicht sofort ausgeführt, sondern erst wenn das nächste Mal die GUI gerendert wird. Die MessageBox behebt das teilweise, weil da eben die GUI neu gezeichnet wird.
Ich würde das ganze so umbauen, das du auf das LoadComplete Event des Browsers wartest, und dann dort mit der Verarbeitung weiter machst.
 
Zuletzt bearbeitet von einem Moderator:
Danke, jetzt habe ich wenigstens einen Anhaltspunkt, wo ich suchen kann. Mit dem LoadComplete hatte ich mir irgendwann schon einmal gedacht, aber den Gedanken mehr oder weniger wieder verdrängt. Ich werde es auf jeden Fall ausprobieren und dann feedback geben.
Nochmals Danke, hier wird einem echt geholfen =)

Edit:

Also,das mit dem DocumentCompleteEvent wäre wohl eine Möglichkeit, aber nicht gerade die Passende, da manchmal auf einer Seite (durch die Frames) mehrere Events abgeschossen werden. Habe eine schönere Möglichkeit gefunden:

nach webBrowser1.navigate(...);
C#:
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete){

                Application.DoEvents();
            }

Scheint auch alles (bis zum nächsten Fehler =) zu funktionieren und ich bin glücklich.

Danke nochmal an alle Helfer, besonders an Steiner_B!
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück