Autor Beitrag
DarkStaRX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 28
Erhaltene Danke: 3



BeitragVerfasst: So 28.04.13 19:53 
Hey Leute,

ich habe ein Problem mit dem Freeze eines Programmes... ich möchte das mein Programm nicht still steht solange es etwas aus dem Internet läd, z.B. den Sourcecode einer Webseite.

Anschließend möchte ich den Sourcecode bearbeiten und am Ende in einem Label anzeigen.

Das Problem ist ich weißß überhaupt nicht wie die Sache mit den Threads funktioniert und das richtig.

Ich habe schon im Netz geschaut aber irgendwie komme ich damit nicht ans Ziel =/.
Also ich kann per Thread einen Text dauerhaft in eine Textbox schreiben lassen ohne dass das Program hängt aber weiter habe ic hes nicht geschafft...

Würde mich freuen wenn ihr mir helfen könntet!

MFG
DArkiii
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: So 28.04.13 23:16 
Du musst
1. Thread erstellen ( mit Parameter true, da er nicht direkt beginnen soll...
2. Link setzten
3. Freeonterminate auf true setzten
4. Resume des threads aufrufen...

Im execute des threads musst du:
Sourcecode laden
Danach bearbeiten
Danach label.Caption auf dein bearbeiteten Code setzten (synchronize)

Reicht das? Oder brauchst du Code?

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 29.04.13 07:13 
Besser:
Dem Thread den Parameter mit der URL gleich mitgeben und den Thread gleich loslaufen lassen.

Resume sollte man nicht nutzen, wenn man FreeOnTerminate nutzt (was ich normalerweise nicht tue, sondern mich selbst um den Thread kümmere).
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Mo 29.04.13 09:24 
Hallo!

Also zuerst einmal, @IhopeonlyReader und @jaenicke: .NET, nicht Delphi ;-)


Nun zur Frage: Je nach verwendeter .NET-Version kann man das unterschiedlich schön lösen. In .NET 4.5 ist das sehr einfach:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
        private async void button1_Click(object sender, EventArgs e)
        {            
            var wc = new WebClient();
            string data = await wc.DownloadStringTaskAsync("http://www.entwickler-ecke.de");
            textBox1.Text = data;
        }


Was hier im Hintergrund passiert: Durch das "async" in der Methodensignatur weiß der Compiler, dass wir eine asynchrone Methode erstellen wollen, also ein Methode in der, einfach gesagt, mit verschiedenen Threads gearbeitet werden soll. In Zeile 3 wird dann ganz normal (und noch im Hauptthread) eine Instanz des WebClients erstellt.

Zeile 4 enthält dann die wahre "Magie". Die Methode DownloadStringTaskAsync gibt in Wahrheit keinen String, sondern einen Task<string> zurück und zwar direkt nach Aufruf. Dieser Task erledigt im Hintergrund (sprich: in einem anderen Thread) den Download. Irgendwann meldet sich der Task dann, dass er fertig ist. Durch das Schlüsselwort await müssen wir uns aber nicht drum kümmern, auf irgendwelche Events des Tasks zu warten. Das macht der Compiler für uns! Wenn wir nämlich in Zeile 5 die Variable data verwenden, ohne dass der Task schon fertig ist, wird dort drauf gewartet, dass er fertig wird. Aber dadurch wird der Hauptthread (und damit die GUI) nicht blockiert, sondern die Methode wird temporär verlassen und erst wieder fortgesetzt, wenn der Download fertig ist. Und das alles ohne unser Zutun, nur mit zwei kleinen Schlüsselwörtern :-)


Wie sieht es mit "altem" .NET aus? So:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
            var wc = new WebClient();
            wc.DownloadStringCompleted += delegate(object sender2, DownloadStringCompletedEventArgs e2)
            {
                textBox1.Text = e2.Result;
            };

            wc.DownloadStringAsync(new Uri("http://www.entwickler-ecke.de"));



Oder ist die Bearbeitung so lang, dass die auch in einen separaten Thread muss? Das kann man dann in .NET 4.5 auch sehr schick lösen :-)

Grüße
Christian

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
DarkStaRX Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 28
Erhaltene Danke: 3



BeitragVerfasst: Di 30.04.13 23:33 
Vielen Dank erstmal für die Hilfe und schöne Erklärung wie das ganze für den "Download" eines Strings von der Webseite funktioniert.

Ich hatte mir jetzt aber dabei erhofft zu erfahren wie ich Threads auch für andere Dinge nutzen kann.
z.B. eine Datenbank auslesen + in Ausgabe ohne dass das Programm hängen bleibt.

Ich habe Beispielsweise ein Programm das den ICQ Verlauf ausliest.
Das Ding ist nur dass die Verläufe manchmal ziemlich lang sind und somit das Programm dann beim auslesen, bzw. bei der Ausgabe ziemlich hängen bleibt bis er alles ausgelesen hat.

Das Problem ist ich habe keinen Schimmer wie ich das in Threads packen kann ohne das die Form darunter leidet und hängen bleibt ^^.

MFG
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Di 30.04.13 23:44 
Von welcher .NET-Version reden wir denn jetzt? Insbesondere .NET 4.5 hat sich sehr dahin entwickelt, dass genau das, was Du willst, die Standardvorgehensweise ist.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
DarkStaRX Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 28
Erhaltene Danke: 3



BeitragVerfasst: Di 30.04.13 23:49 
Ich arbeite eher mit dem aktuellen .NET Framework also kann es ruhig 4.5 sein.

Programmieren to ich mit C#
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Mi 01.05.13 15:50 
Dann kannst Du ganz gut mit der Task-Klasse arbeiten. So z.B.:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
        private async void btAddUser_Click(object sender, EventArgs e)
        {
            await Task.Run(() => { Thread.Sleep(5000); });
            MessageBox.Show("foo");
        }


Hier ist hast Du wieder das async-Schlüsselwort in der Methodensignatur und das await-Schlüsselwort beim Aufruf. Der Code, der bei Dir dann z.B. das Auslesen der ICQ-History wäre, ist bei mir jetzt einfach mal Thread.Sleep, was ja den Hauptthread eigentlich blockieren würde, es in diesem Fall aber nicht tut. Trotzdem wird die MessageBox erst nach den fünf Sekunden Wartezeit angezeigt.

Es gibt auch noch die generische Überladung von Task.Run, mit der Du einen Wert zurückliefern kannst:
ausblenden C#-Quelltext
1:
string foo = await Task.Run<string>(() => { Thread.Sleep(5000); return "foo"; });					


Bei längeren Quelltext-Abschnitten würde ich dann eigene Methoden erstellen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
        private async Task<string> ReadICQLogAsync()
        {
            DoSomething();

            await DoSomethingElseAsync();

            DoSomethingDiffernt();

            return await ParseICQLogAsync();
        }


        private async void btAddUser_Click(object sender, EventArgs e)
        {
            string log = await ReadICQLogAsync();

            
            MessageBox.Show("foo");
        }


Konkreter kann ich nicht werden, wenn Du nicht konkreter fragst. Es macht keinen Sinn, jetzt seitenweise Erklärungen zu schreiben, ohne zu wissen, was davon Du eigentlich brauchst :nixweiss:

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

Für diesen Beitrag haben gedankt: DarkStaRX
DarkStaRX Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 28
Erhaltene Danke: 3



BeitragVerfasst: Sa 08.06.13 03:47 
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
Hallo!

Also zuerst einmal, @IhopeonlyReader und @jaenicke: .NET, nicht Delphi ;-)


Nun zur Frage: Je nach verwendeter .NET-Version kann man das unterschiedlich schön lösen. In .NET 4.5 ist das sehr einfach:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
        private async void button1_Click(object sender, EventArgs e)
        {            
            var wc = new WebClient();
            string data = await wc.DownloadStringTaskAsync("http://www.entwickler-ecke.de");
            textBox1.Text = data;
        }


.........

....
....

Grüße
Christian


Irgendwie funktioniert das damit aber noch nicht wirklich...
Meine Form1 mit der ich dann währenddessen weiter arbeiten möchte ist gefreezd.

habe nur dein Code Copy / Paste versucht und freezed genauso wie sonst auch

MFG
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 20451
Erhaltene Danke: 2264

Win 10
C# (VS 2019)
BeitragVerfasst: Sa 08.06.13 13:04 
Irgendwas musst Du anders machen, weil es so funktioniert :nixweiss:

Zeig mal Deinen Quelltext.

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