Autor Beitrag
Script1996
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Sa 05.04.14 19:05 
Hey zusammen,

ich habe hier mal einen Auszug aus meinem Code:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
HtmlElement text = webBrowser1.Document.GetElementById("status");
            string content = text.InnerText;
            
            while(content.Contains("Searching")){


                MessageBox.Show("Auffangen");
                
                HtmlElement nachsuche = webBrowser1.Document.GetElementById("status");
                content = nachsuche.InnerText;
            }


Also kurz gesagt: Wenn der Status auf "Searching" ist soll er einfach warten bis der Status geändert wurde.
Mit einer MessageBox klappt es einwandfrei. Doch ich möchte das alles automatisieren also ohne MessageBox.Show("Auffangen").
Doch dann hängt sich die Applikation auf..

Was ist daran Falsch ?

Mit freundlichem Gruß,
Script

Moderiert von user profile iconChristian S.: Highlight- durch C#-Tags ersetzt
C#
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 561
Erhaltene Danke: 65

Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
BeitragVerfasst: Sa 05.04.14 22:42 
Hast du mal versucht die Schleife zu drosseln? Einfach mal n Thread.Sleep(10) oder sowas rein. Mehr fällt mir auch nicht ein.

_________________
Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Sa 05.04.14 23:11 
Du hast die Schleife im selben Thread?

Dann ist das auch klar, denn die Schleife arbeitet fleißig in irgendeiner Methode und lässt dem Rest der Anwendung nicht die Möglichkeit.

Sowas sollte man in einen extra Thread auslagern, wo die Schleife dann fröhlich vor sich hin läuft und irgendwann die Info in den Haupt-Thread gibt, dass sich da was getan hat.

So kann z.B. eine Oberfläche weiter laufen, meinetwegen alles gesperrt und eine Info, dass gerade nichts getan wird.


Es gibt da aber auch etwas viel besseres: Events

Ich kenne mich mit dem Browser nicht wirklich aus, aber ich denke, es gibt bestimmt irgendwo ein Event, das geworfen wird, wenn der Content sich ändert. Da kannst du dann horchen und prüfen, ob der Content so aus sieht, wie du das willst.

Für diesen Beitrag haben gedankt: Script1996
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 06.04.14 12:33 
Das Event ist DocumentCompleted:
msdn.microsoft.com/d...cumentcompleted.aspx
Script1996 Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: So 06.04.14 20:14 
user profile iconPalladin007 hat folgendes geschrieben Zum zitierten Posting springen:
Du hast die Schleife im selben Thread?

Dann ist das auch klar, denn die Schleife arbeitet fleißig in irgendeiner Methode und lässt dem Rest der Anwendung nicht die Möglichkeit.

Sowas sollte man in einen extra Thread auslagern, wo die Schleife dann fröhlich vor sich hin läuft und irgendwann die Info in den Haupt-Thread gibt, dass sich da was getan hat.

So kann z.B. eine Oberfläche weiter laufen, meinetwegen alles gesperrt und eine Info, dass gerade nichts getan wird.


Es gibt da aber auch etwas viel besseres: Events

Ich kenne mich mit dem Browser nicht wirklich aus, aber ich denke, es gibt bestimmt irgendwo ein Event, das geworfen wird, wenn der Content sich ändert. Da kannst du dann horchen und prüfen, ob der Content so aus sieht, wie du das willst.


Hey,

Das mit dem Event glaube ich funktioniert nicht. Die Homepage ist ja in dem Sinne schon geladen. Es wird nur über ein Javascript "aktualisiert" ..
Gibt's da ein schönes Tutorial wie ich Threads auslagere? Bin noch relativ neu in C# und mach das nur spaßeshalber :D

@ C#
Das Thread.Sleep hängt das Programm leider auch auf.

Mit freundlichem Gruß,
Script
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 06.04.14 21:03 
Wenn Du .NET 4.5 benutzt, kannst Du es recht leicht über async / await lösen. Das wurde genau dafür "gebaut", dass Programme nicht mehr blockieren, aber der Code immer noch so lesbar ist, wie man es gewohnt ist.

Nachfolgend siehst Du einen Button-Klick-Eventhandler, welcher folgendes tut: Er wartet, bis ich in eine Textbox den Text "fertig" geschrieben habe, dann wird eine MessageBox angezeigt. Offensichtlich darf das Programm dabei nicht blockieren, denn sonst könnte ich nicht in die TextBox schreiben. ;-)

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
    private async void button1_Click(object sender, EventArgs e)
    {
      await Task.Run(() =>
      {
        while(!textBox1.Text.Contains("fertig"))
          Thread.Sleep(10);
        
      });

      MessageBox.Show("foo");
    }


Was im Hintergrund passiert, ist, dass der Task mit der Schleife im Hintergrund gestartet wird (also nicht blockiert). Durch das "await" weist man den Compiler an, mit der Ausführung des Rests der Methode zu warten, bis der Task im Hintergrund fertig ist (also wenn der Text "fertig" in der TextBox steht). Sobald das der Fall ist, kehrt das Programm in die Methode zurück und die MessageBox wird angezeigt.

Ich weiß, das ist für einen C#-Neuling nicht einfach zu verstehen, aber es ist eine so wunderbare Art, Dinge im Hintergrund zu erledigen, dass man das gar nicht früh genug lernen kann ;-)

//edit: Du wirst nach den Namespace System.Threadings.Tasks einbinden müssen.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".

Für diesen Beitrag haben gedankt: Script1996
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 06.04.14 21:19 
Das habe ich noch nicht in der Form benutzt (Zugriff auf UI in await), aber muss man den Zugriff auf textBox1.Text in dem await nicht explizit im Kontext des Hauptthreads machen?
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 06.04.14 21:43 
Hm. Jetzt wo Du es sagst :gruebel: Eigentlich müsste man das, hat aber so gelaufen. War wahrscheinlich nur Glück ;-)

Dann eventuell so, auch wenn es schon nicht mehr so schön aussieht ;-)

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
    private async void button1_Click(object sender, EventArgs e)
    {
      await Task.Run(() =>
      {
        string textBoxText = "";
        Action a = () => { textBoxText = textBox1.Text; };
        do
        {
          Thread.Sleep(10);
          Invoke(a);
        } while (!textBoxText.Contains("fertig"));        
      });

      MessageBox.Show("foo");
    }


@Script1996: Mein erster Quelltext hatte den Fehler, dass ich aus einem anderen Thread auf die Textbox zugegriffen habe. Sowas kann böse in die Hose gehen, man sollte auf Elemente der Benutzeroberfläche auch nur vom Thread der Benutzeroberfläche aus zugreifen. Das tue ich mit obigem Quelltext. Ich habe eine Action "a" angelegt (sowas wie eine kleine Methode innerhalb einer Methode), welche mir den Inhalt der TextBox in meine lokale Variable "textBoxText" schreibt. Diese Action rufe ich mittels Invoke dann im Thread der Benutzeroberfläche auf.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".

Für diesen Beitrag haben gedankt: Script1996
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: So 06.04.14 22:22 
Geht so bestimmt schon, ist aber halt trotzdem etwas doof zum lesen ;-)

So müsste es aber auch gehen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
private async void button1_Click(object sender, EventArgs e)
{
  while(!textBox1.Text.Contains("fertig")) // Polling
    await Task.Delay(20);

  MessageBox.Show("foo");
}

Task.Delay blockt nicht (wie Sleep) sondern wartet "asynchron". Der GUI Thread kann in der Zwischenzeit also anderes Zeug erledigen, das ganze funktioniert hier also ähnlich wie ein Timer.

Für diesen Beitrag haben gedankt: Christian S., Script1996
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: So 06.04.14 22:30 
Ah, das ist natürlich viel schöner :zustimm:

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Script1996 Threadstarter
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Mi 09.04.14 20:58 
Hey ihr,


vielen Dank schonmal für eure Antworten ! :)

Habe mir mal VS2012 zugelegt. Nun sieht mein Code so aus:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
while (content.Contains("Searching"))
            {
                await Task.Delay(20);
            }
                MessageBox.Show("foo");


Aufhängen tut sich nix .. jedoch kommt auch keine MessageBox nachdem nichtmehr "Searching" dasteht.

Habt ihr noch ne Idee ?


EDIT:

Ich Pflaume :)
hab den content in der while-Schleife ja garnicht ändern lassen..

Passt alles Perfekt !!! Vielen Lieben Dank!