Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Nicht alle Threads werden bearbeitet?! ... (https://www.delphipraxis.net/28172-nicht-alle-threads-werden-bearbeitet.html)

emploi 20. Aug 2004 12:41


Nicht alle Threads werden bearbeitet?! ...
 
Huhu,

mal wieder ein Thread Problem nachdem ich den Stack Overflow wohl wegbekommen hab.
Ich zeig euch erstmal ein wenig Code und erläuter dann was das Problem ist:


Thread Aufruf Unit (Ausschnitt):
Code:
PROCEDURE CurrentPage(WebBrowser1:TWebBrowser; aSID:STRING; App:TApplication);
VAR temp : TStringList;
    ThreadArray : ARRAY of CheckThread;
    j : Integer;
BEGIN
    temp := TStringList.Create;
    TRY
      GetUrls(WebBrowser1,temp);

      SetLength(ThreadArray,temp.Count);
      counter := temp.Count; // globale Variable die die Anzahl der gestarteten Threads festhält!
      FOR j := 0 TO temp.Count - 1 DO
      BEGIN
        ThreadArray[j] := CheckThread.Create(True);
        WITH ThreadArray[j] DO
        BEGIN
          SID := aSID;
          url := temp.Strings[j];
          FIndex := j; // Indizierung der Threads
          FreeOnTerminate := True;
          Resume;
        END;
      END;

      WHILE ((counter <> 0) AND (uscs_form.GetGoOn)) DO // GoOn - Abbruch Variable in der Main Form
            App.ProcessMessages;
    FINALLY
      temp.Free;
    END;
END;


PROCEDURE ThreadReady;
BEGIN
    dec(counter);
END;

Thread Unit:
Code:
procedure CheckThread.Execute;
var IdHttp1 : TIdHTTP;
    Request : TStringList;
    MyStream : TMemoryStream;
    done : boolean;
begin
  WHILE NOT(done) DO
  BEGIN
    IdHttp1 := TIdHTTP.Create(nil);
    Request := TStringList.Create;
    MyStream := TMemoryStream.Create;
    TRY
        done := False;
        idHttp1.RedirectMaximum := 15;
        idHttp1.HandleRedirects := True;
        TRY
          IdHttp1.Request.ContentType := 'application/x-www-form-urlencoded';
          Request.Add('&PHPSESSID='+SID);
          IdHttp1.Post(url,Request,MyStream);
          MyStream.WriteBuffer(#0' ', 1);
          MyStream.Position := 0;
          ...
          done := True;
        EXCEPT
        ON Exception DO
           done := False;
        END;
        IF done THEN
           Synchronize(SendUrl);
    FINALLY
      MyStream.Free;
      Request.Free;
      IdHttp1.Free;
    END;
  END;
END;
Dazu schon mal die erste Frage, ist das günstig das so in einer While schleife zu
gestalten? Ich werd die Exception warscheinlich dann noch spezifisch auf
den Socket Error ausrichten, aber prinzipiell soll der das halt so oft
probieren bis er es geschafft hat. ist das zu aufwendig weil er jedes
mal die objecte neu erzeugt?


Weiter Thread Unit:
Code:
PROCEDURE CheckThread.SendUrl;
BEGIN
   uscs_util.ThreadReady;
   uscs_form.UpdateFromThread(inttostr(FIndex)); // soll später eigentlich etwas anderes machen
END;                                             // übergebe zu Test Zwecken den Index

Main Unit:
Code:
procedure Tuscs_form.UpdateFromThread(Furl:String);
begin
      IF Furl <> '' THEN
          uscs_result_form.LB_results.Items.Add(Furl);  // Schreibt die ganzen Thread Index Nummern
end;                                                    // in eine Listbox!

das Problem ist jetzt wenn er z.b. 16 Threads startet, dann dauert es ein wenig
aber dann sind kommen nach und nach die Index Einträge in der Listbox.
natürlich nicht sortiert. das Problem ist von den 16 fehlen dann die ersten
drei! Immer auch wenn es mal nur 10 threads sind oder mehr als 16. Die ersten
drei fehlen irgendwie immer. und ich hab keine ahnung warum die nicht auch
aufgeführt werden?!

[EDIT]
also sind doch nicht immer die ersten. teilweise fehlen einfach
welche zwischendurch, komischerweise häufen sich aber auch der
1-3 thread die fehlen. muss ja dann irgendwie an der Execute
Methode des Thread liegen. weiss aber nicht wo der fehler ist :(
[/EDIT]

Ist das überhaupt, günstig dass über die

Code:
WHILE ((counter <> 0) AND (uscs_form.GetGoOn)) DO // GoOn - Abbruch Variable in der Main Form
    App.ProcessMessages;
Schleife darauf gewartet wird, dass alle Fertig sind?


Wäre euch sehr dankbar wenn ihr mir helfen könntet!

mfg emploi

Blutiger Anfänger 21. Aug 2004 23:21

Re: Nicht alle Threads werden bearbeitet?! ...
 
Die VCL ist NICHT (!!!) threadsafe. Das was du machen willst, solltest du über den normalen Weg (komplette Trennung des Threads vom Hauptthread) erreichen und dann über Window Messages das Feedback an das Hauptform weitergeben. Denk dran, daß es Systeme (HT und MP) gibt, die mehrere Threads tatsächlich gleichzeitig ausführen! Da solltest du auch mit Exclusion Objects arbeiten (Mutexe, Semaphoren, Critical Sections ...). Das Problem dürfte bei dir echt daran liegen, daß die VCL eben nicht threadsafe ist.

emploi 22. Aug 2004 00:24

Re: Nicht alle Threads werden bearbeitet?! ...
 
Zitat:

Zitat von Blutiger Anfänger
Die VCL ist NICHT (!!!) threadsafe. Das was du machen willst, solltest du über den normalen Weg (komplette Trennung des Threads vom Hauptthread) erreichen und dann über Window Messages das Feedback an das Hauptform weitergeben.

Und wie soll ich das machen also den "normalen" weg?

haste links oder sowas?

danker für die antwort!

mfg emploi

Blutiger Anfänger 22. Aug 2004 00:33

Re: Nicht alle Threads werden bearbeitet?! ...
 
Versuche einfach die Arbeit konsequent zu trennen. Ein Arbeitsthread hat nix mit dem Form rumzufummeln. Das Form sollte entsprechend der Architektur von Windows benachrichtigt werden. Dazu gibt es zB WMs.

Ganz nebenbei macht die WHILE-Schleife eigentlich die Nutzung von Threads überflüssig, da spätestens an der WHILE-Schleife alles wieder zusammenläuft ... oder?

emploi 22. Aug 2004 00:54

Re: Nicht alle Threads werden bearbeitet?! ...
 
du meinst die while schleife nach dem aufruf?

ich will mit meinen threads nur erreichen das
die idhttp aufrufe parallel nebeneinander ablaufen können
und nicht nacheinander, weil das zu lange dauert.

und damit mein programm nicht damit fortfährt die nächsten
threads zu starten, damit ich nicht auf einmal 100 gestartet habe
will ich halt warten das die gestarteten threads fertig sind.

cool das du noch wach bist :) [EDIT] .. warst .. [/EDIT]

Blutiger Anfänger 22. Aug 2004 01:15

Re: Nicht alle Threads werden bearbeitet?! ...
 
Verstehe schon, aber es gibt Funktionen die dies erledigen:

WaitForMultipleObjects()

Und das parallele Ablaufen geht auch ohne, daß irgendein Zugriff auf die VCL stattfindet (unter der Annahme die Indys seien nicht teil der VCL). Die dürften doch threadsafe sein? Ich selber nutze sie nicht.

emploi 22. Aug 2004 11:49

Re: Nicht alle Threads werden bearbeitet?! ...
 
ok, dann werd ich es mal damit versuchen!

meinst du den zugriff auf die vcl in der
Prozedur:

Code:
PROCEDURE CheckThread.SendUrl;
BEGIN
   uscs_util.ThreadReady;
   uscs_form.UpdateFromThread(inttostr(FIndex)); // soll später eigentlich etwas anderes machen
END;

Blutiger Anfänger 22. Aug 2004 11:51

Re: Nicht alle Threads werden bearbeitet?! ...
 
Japp.

Snychronize führt die Func im Kontext des Hauptthreads aus, das sollte also nicht zuviele Probleme geben ... müßte mir wohl mal die Indys holen um es zu testen. Wird aber vor morgen nix.

emploi 22. Aug 2004 15:41

Re: Nicht alle Threads werden bearbeitet?! ...
 
Hm komisch und irgendwie prägnant für das Problem ist, dass wirklich
zu 90 % die ersten 3-4 Threads bzw deren Index nicht in meiner Listbox
auftreten.

Synchronize wird nur aufgerufen wenn es keine Exception gegeben hat.
weil nur dann ist done = true!

Ich hab die Execute Procedur jetzt mal umgestellt
und jetzt werden auch die threads 0-4 in meiner listbox
angezeigt :) komischerweise fängt die liste damit immer
an. also immer 0 - 4 in reihenfolge.die nachfolgenden
Indizes die aufgelistet werden sind dann durcheinander.
Kann es sein das es etwas mit den zulässigen Verbindungen
des Servers zu tun hat? 0-4 werden direkt zugelassen
und damit auch als erste fertig während die anderen
danach in der warteschleife (also meine while schleife im
thread) hängen und dann erst nach und nach abgearbeitet werden
können?!

irgendwie ist das alles sehr komisch.

Code:
procedure CheckThread.Execute;
var IdHttp1 : TIdHTTP;
    Request: TStringList;
    MyStream : TMemoryStream;
    done : boolean;
begin
  WHILE NOT(done) DO
  BEGIN
    IdHttp1 := TIdHTTP.Create(nil);
    Request := TStringList.Create;
    MyStream := TMemoryStream.Create;
    TRY
        done := False;
        idHttp1.RedirectMaximum := 15;
        idHttp1.HandleRedirects := True;
        TRY
          IdHttp1.Request.ContentType := 'application/x-www-form-urlencoded';
          Request.Add('&PHPSESSID='+SID);
          IdHttp1.Post(url,Request,MyStream);
          MyStream.WriteBuffer(#0' ', 1);
          MyStream.Position := 0;
          ...
          done := True;
        EXCEPT
        ON Exception DO
           done := False;
        END;
    FINALLY
      MyStream.Free;
      Request.Free;
      IdHttp1.Free;
    END;
  END;
  IF done THEN
      Synchronize(SendUrl);
END;

Blutiger Anfänger 22. Aug 2004 16:01

Re: Nicht alle Threads werden bearbeitet?! ...
 
Wenn der "Server" kein XP mit SP2 ist, gibt es keine Probleme.

Wenn du willst, kannst du mir mal dein Beispiel (wichtigste Stellen) als Source anhängen und per Mail an mich schicken. Kontakt: http://assarbad.net

Testen wird aber vermutlich erst morgen (u.U. auch schon heute, aber unwahrscheinlich) -muß mir auch erstmal die Indys besorgen. Welches Delphi benutzt du?

emploi 22. Aug 2004 17:30

Re: Nicht alle Threads werden bearbeitet?! ...
 
steht bei mir neben den postings :)

Borland Delphi 7 Enterprise


Bist du Assarbad?

[EDIT]
Es scheint übrigens zu laufen ;)
Das Problem sind nur die zu häufigen Anfragen
hintereinander. da blockt mich der server für ne
gewisse zeit, hab daher noch nen sleep eingebaut,
aber wie gesagt scheint zu klappen.
ob es sonderlich sicher ist und auf anderen
systemen (ich hab win2k laufen) lübbbt - k.a.
muss ich mal testen.
[/EDIT]

APP 22. Aug 2004 17:44

Re: Nicht alle Threads werden bearbeitet?! ...
 
Hallo emploi,

Oliver wird Deinen Code morgen netterweise prüfen,
ich habe im "Drüberfliegen" nur ein paar Sachen
gefunden, die Du vielleicht überdenken solltest:

"Done" ist eine lokale Variable, die, im Unterschied zu globalen Variablen,
solange nicht initialisiert ist, bis ihr ein Wert zugewiesen wurde.
Daher wird Deine Whileschleife IMHO wohl nicht immer funktionieren.

Ich würde die Abbruchbedingung noch einmal überdenken, man sollte niemals
eine Exception zur Steuerung einer Schleife verwenden.
Soweit ich sehe ist IdHttp1.Post eine Funktion die einen String zurückgibt,
ich nehme an, diesen kannst Du auswerten.
(Ich habe die Indies zwar installiert, aber leider die Hilfe dazu nicht :oops:)

Was passiert eigentlich mit Deiner Schleife,
wenn sie "o0" (unendlich) viele Exceptions produziert?

Bei einer Thread.Execute Schleife würde ich empfehlen, zusätzlich
Delphi-Quellcode:
WHILE (NOT Terminated) OR (NOT Application.Terminated)
einzubauen,
sonst läuft dein Thread nach Programmende "ewig und 3 Tage" weiter.

[HELLSEHMODUS EIN]
Blutiger Anfänger = Oliver = Assarbad :mrgreen:
[/HELLSEHMODUS AUS]

emploi 22. Aug 2004 19:27

Re: Nicht alle Threads werden bearbeitet?! ...
 
Zitat:

Zitat von APP
Hallo emploi,

"Done" ist eine lokale Variable, die, im Unterschied zu globalen Variablen,
solange nicht initialisiert ist, bis ihr ein Wert zugewiesen wurde.
Daher wird Deine Whileschleife IMHO wohl nicht immer funktionieren

geändert.


Zitat:

Zitat von APP
Ich würde die Abbruchbedingung noch einmal überdenken, man sollte niemals
eine Exception zur Steuerung einer Schleife verwenden.
Soweit ich sehe ist IdHttp1.Post eine Funktion die einen String zurückgibt,
ich nehme an, diesen kannst Du auswerten.
(Ich habe die Indies zwar installiert, aber leider die Hilfe dazu nicht :oops:)

Öhm weiss ich nicht so genau. Wenn der Indy Methode Post nicht erlaubt wird
zu connecten kommt ne "Socket Error" Exception. Hab oben im Thread auch schonmal
geschrieben das ich die Try Exception Schleife speziell darauf nochmal
ausrichten werde!


Zitat:

Zitat von APP
Was passiert eigentlich mit Deiner Schleife,
wenn sie "o0" (unendlich) viele Exceptions produziert?

Das sollte eigentlich nicht passieren. aber.. siehe oben.

Zitat:

Zitat von APP
Bei einer Thread.Execute Schleife würde ich empfehlen, zusätzlich
Delphi-Quellcode:
WHILE (NOT Terminated) OR (NOT Application.Terminated)
einzubauen,
sonst läuft dein Thread nach Programmende "ewig und 3 Tage" weiter.

Um Application.Terminated zu benutzen müsste ich die Application erstmal
an den Thread übergeben und ich denke das wäre schon wieder mist!
Und warum sollte ich WHILE NOT(Terminated) einbauen wenn ich eh nicht
vorhab die Threads von aussen zu beenden? Ausserdem hab ich glaub ich mal
gelesen das die Threads auch beendet werden wenn der Process beendet wird?!

mfg emploi

Blutiger Anfänger 23. Aug 2004 14:35

Re: Nicht alle Threads werden bearbeitet?! ...
 
Zitat:

Zitat von APP
[HELLSEHMODUS EIN]
Blutiger Anfänger = Oliver = Assarbad :mrgreen:
[/HELLSEHMODUS AUS]

[TANZT-WIE-RUMPELSTILZCHEN]
Das hat dir der Teufel gesagt, das hat dir der Teufel gesagt ...
[/TANZT-WIE-RUMPELSTILZCHEN]

Blutiger Anfänger 23. Aug 2004 14:39

Re: Nicht alle Threads werden bearbeitet?! ...
 
Zitat:

Zitat von emploi
Um Application.Terminated zu benutzen müsste ich die Application erstmal
an den Thread übergeben und ich denke das wäre schon wieder mist!
Und warum sollte ich WHILE NOT(Terminated) einbauen wenn ich eh nicht
vorhab die Threads von aussen zu beenden? Ausserdem hab ich glaub ich mal
gelesen das die Threads auch beendet werden wenn der Process beendet wird?!

Es gibt einen Unterschied zwischen "nettem" Beenden (graceful) und dem Beenden eines Threads duch das System (kill).


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:35 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz