Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Threadproblem auf einem "langsameren" Rechner (https://www.delphipraxis.net/84757-threadproblem-auf-einem-langsameren-rechner.html)

RWarnecke 21. Jan 2007 10:53


Threadproblem auf einem "langsameren" Rechner
 
Hallo zusammen,

ich habe folgendes Problem, ich rufeso meine zwei Thread aus dem Haupttread auf :
Delphi-Quellcode:
      try
        SearchForDelete := TSearchDelete.Create(false);
        SearchForDelete.FreeOnTerminate := False;
        SearchForCopy := TSearchCopy.Create(false);
        SearchForCopy.FreeOnTerminate := False;
        ThreadArray[0] := SearchForCopy.Handle; // Handle Array füllen
        ThreadArray[1] := SearchForDelete.Handle;
        repeat
          // Auf Threads warten
          dwWaitResult := msgWaitforMultipleObjects(length(ThreadArray), ThreadArray, true, 10, QS_ALLINPUT);
          if dwWaitResult <> WAIT_OBJECT_0 then
          begin
            Application.ProcessMessages; // GUI aktualisieren
            PeekMessage(msg, Application.Handle, 0, 0, PM_REMOVE);
            PeekMessage(msg, SearchForCopy.Handle, 0, 0, PM_REMOVE);
            PeekMessage(msg, SearchForDelete.Handle, 0, 0, PM_REMOVE);
          end;
          if CancelSync then
          begin
            TerminateThread(ThreadArray[0], 0);
            TerminateThread(ThreadArray[1], 0);
            dwWaitResult := WAIT_OBJECT_0;
          end;
        until dwWaitResult = WAIT_OBJECT_0; // keinen Threads mehr zum warten
      finally
        SearchForCopy.Free;
        SearchForDelete.Free;
      end;
Die beiden Threads machen nichts anderes als Verzeichnisse zu vergleichen und mir die aktuellen Dateien, die gerade verglichen werden in einem Fenster anzuzeigen. Nach dem finally, wird das Fenster geschlossen und dann die Ergebnisliste angezeigt. Wenn ich diesen Aufruf auf meinem AMD Athlon 64 3200+ aufrufe, funktioniert alles wunderbar. Wenn ich jetzt das gleiche Programm auf meinem IBM Thinkpad 1GHz aufrufe, muss ich immer erst die Maus über das Fenster bewegen, dass das Programm die Ergebnisliste anzeigt.

Weiß jemand rat, warum das so ist ?

Der_Unwissende 21. Jan 2007 11:01

Re: Threadproblem auf einem "langsameren" Rechner
 
Hi,
wie läuft denn die Anzeige der Dateien ab? Hast Du denn dort berücksichtigt, dass diese Anzeige synchronisiert werden muss?

Gruß Der Unwissende

RWarnecke 21. Jan 2007 11:10

Re: Threadproblem auf einem "langsameren" Rechner
 
Zitat:

Zitat von Der_Unwissende
wie läuft denn die Anzeige der Dateien ab?

Die Anzeige läuft über eine extra Unit und einer Property. Die Property wird innerhalb der extra UNit gefüllt und dann abgefragt und an das Label übergeben. Das funktiniert ja auch soweit alles wunderbar. Nur der Sprung von dem Fenster mit den Labels zur Ergebnisliste, funktioniert erst dann, wenn die Maus über das Programmfenster bewegt wird.

Zitat:

Zitat von Der_Unwissende
Hast Du denn dort berücksichtigt, dass diese Anzeige synchronisiert werden muss?

Tja, dass mit dem synchronisieren verstehe ich noch nicht ganz. Aber hat das Synchronisieren denn etwas mit dem Warten auf die Threads zu tun :?:

Edit:
Auf dem Athlon 64 3200+ läuft ja alles bestens. Alles ohne Probleme.

Edit 2:
Auch jetzt läuft es nichtmehr auf dem Athlon 64 3200+. Ich werde noch wahnsinnig mit Threads :spin2: :firejump: :wall: Lasse ich alles über meine Statusbar laufen im Hauptfenster, dann funktioniert alles wunderbar auf beiden Rechnern.

C.Schoch 21. Jan 2007 17:04

Re: Threadproblem auf einem "langsameren" Rechner
 
Hi,
Nicht verzweifeln!
Das Problem hatte auch schon nur mit DualCore Rechnern.
Ich habs jetzt so laufen, funktioniert Tip Top
Delphi-Quellcode:
var
ThreadArray : array[0..1] of THandle;
dwWaitResult := WaitforMultipleObjects(length(ThreadArray), @ThreadArray, true, 100);
Mir wurde gesagt, das Windows erst wenn alle Threads beendet sind und eine Message ansteht WAIT_OBJECT_0 zurückgibt. komischerweise gings bei mir anfänglich auch problemlos.

Edit: Hatte damals einen Thread aufgemacht Hier
Edit2: Deklaration von ThreadArray geändert um Missverständnisse zu vermeiden

thkerkmann 21. Jan 2007 17:24

Re: Threadproblem auf einem "langsameren" Rechner
 
Hi,

Zitat:

Zitat von C.Schoch
Hi,
Nicht verzweifeln!
Das Problem hatte auch schon nur mit DualCore Rechnern.
Ich habs jetzt so laufen, funktioniert Tip Top
Delphi-Quellcode:
var
ThreadArray : array[0..3] of THandle;
dwWaitResult := WaitforMultipleObjects(length(ThreadArray), @ThreadArray, true, 100);
Mir wurde gesagt, das Windows erst wenn alle Threads beendet sind und eine Message ansteht WAIT_OBJECT_0 zurückgibt. komischerweise gings bei mir anfänglich auch problemlos.

Edit: Hatte damals einen Thread aufgemacht Hier

Was ist das? Experimentelle Datenverarbeitung?

Es gibt 2 Threads, also sollte wohl die Länge des ThreadArray und damit der Count für msgWaitForMultipleObjects auf 2 sein. Oder hab ich was übersehen? :gruebel:

Ich denke das Problem ist msgWait... weil es müssen die zwei Threads zuende gelaufen sein UND ein Ereignis in der MessageQueue sein (QS_ALL_INPUT). Das heist, das passiert wohl mit der Maus. Das es auf dem einen Rechner mal läuft ist wohl eher ein Zufall (vielleicht gegen die Maus gestubst ?).

Der Ansatz mit WaitForMultipleObjects wäre wohl besser, mit einem kurzen Timeout (10 msec war schon nicht schlecht) und dann einfach ein Applicaction.ProcessMessages. Die beiden PeekMessage verstehe ich nicht, wozu sollen die dienen? Die nehmen doch wieder nur Messages aus der Queue, die dir dann fehlen. Oder hab ich auch hier was übersehen ? :gruebel:

Gruss

C.Schoch 21. Jan 2007 17:44

Re: Threadproblem auf einem "langsameren" Rechner
 
Die Deklaration von ThreadArray stammt aus meinem Projekt in dem 4 Threads zum Warten vorhanden sind.
Ich wollte damit eigentlich nur die Deklaration verdeutlichen.
Das Peakmessage versteh ich auch nicht da sollte am besten nur Application.Processmessages hin sonst reagiert die Form ja trotz Threads nicht mehr.

RWarnecke 24. Jan 2007 20:59

Re: Threadproblem auf einem "langsameren" Rechner
 
Hallo zusammen,

erstmal ein dickes Danke an Euch. Ich habe den Teil des Codes jetzt so geändert :
Delphi-Quellcode:
      try
        SearchForDelete := TSearchDelete.Create(False);
        SearchForDelete.FreeOnTerminate := False;
        SearchForCopy := TSearchCopy.Create(False);
        SearchForCopy.FreeOnTerminate := False;
        ThreadArray[0] := SearchForCopy.Handle; // Handle Array füllen
        ThreadArray[1] := SearchForDelete.Handle;
        repeat
          // Auf Threads warten
          dwWaitResult := WaitforMultipleObjects(length(ThreadArray), @ThreadArray, true, 10);
          if dwWaitResult <> WAIT_OBJECT_0 then
          begin
            Application.ProcessMessages; // GUI aktualisieren
          end;
          if CancelSync then
          begin
            TerminateThread(ThreadArray[0], 0);
            TerminateThread(ThreadArray[1], 0);
            dwWaitResult := WAIT_OBJECT_0;
          end;
        until dwWaitResult = WAIT_OBJECT_0; // keinen Threads mehr zum warten
      finally
        SearchForCopy.Free;
        SearchForDelete.Free;
      end;
Dieses funktioniert seeeehr gut. Ich habe nur noch ein kleines Problem mit den Labels, die während der Ausführung von den beiden Threads auf dem langsamen Rechner nicht funktioniert. Auf schnelleren Rechnern habe ich das Problem nicht. Ich habe mich mal durch ein paar Tutorials gelesen. Da habe ich den Begriff 'Synchronisieren' aufgegriffen. Wie funktioniert das mit dem Synchronisieren und muss ich das in diesem Teil des Codes einsetzen oder als extra Procedure in der Klasse TThread ?

C.Schoch 25. Jan 2007 17:32

Re: Threadproblem auf einem "langsameren" Rechner
 
Hi,
Das mit dem Syncronisieren geht so, Alles was mit dem Hauprogramm zu tun hat wird mit der Funktion Syncronize auferufen
Delphi-Quellcode:
{ Wichtig: Methoden und Eigenschaften von Objekten in visuellen Komponenten dürfen
  nur in einer Methode namens Synchronize aufgerufen werden, z.B.}

      Synchronize(UpdateCaption);

  //und UpdateCaption könnte folgendermaßen aussehen:

    procedure Thread.UpdateCaption;
    begin
      Form1.Caption := 'Aktualisiert in einem Thread';
    end;
Leider kann man der Prozedur/Funktion die Innehalb von Syncronize steht keine Parameter übergeben.
Falls du also eine Variable Caption übergeben willst muss eine Variable Thread global definiert sein

RWarnecke 29. Jan 2007 17:22

Re: Threadproblem auf einem "langsameren" Rechner
 
Danke an euch alle, jetzt funktioniert meine synchronisation mit den Threads und das die Ergebnisliste gleich angezeigt wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:30 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