Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Rückgabewert von Threads (https://www.delphipraxis.net/162833-rueckgabewert-von-threads.html)

Hannes91 6. Sep 2011 19:18

Rückgabewert von Threads
 
Guten Abend,

in einem Programm lasse ich anfallende rechenintensive Arbeit von mehreren Threads parallel erledigen. Neue Aufgaben sollen erst wieder verteilt werden, wenn alle Threads fertig gerechnet haben und alle Ergebnisse im Hauptprogramm abgelegt worden sind.
Und genau bei letzterem fehlen mir noch brauchbare / elegante Ideen.
Z.B. könnte ich mittels OnTerminate nach Beendigung der Berechnung eines Threads und VOR Freigabe des Threads eine Methode ausführen, jedoch sehe ich hier das Problem, dass diese Methode nicht weiß, welcher Thread gerade fertig geworden ist (dann könnte sie über eine simple Get-Funktion die Rückgabewerte holen und ins Hauptprogramm bringen).
Gibt es da etwa Elegantes oder bin ich da unter Schönheitsaspekten auf dem Holzweg?

Liebe Grüße

Hannes

Uwe Raabe 6. Sep 2011 19:28

AW: Rückgabewert von Threads
 
Zitat:

Zitat von Hannes91 (Beitrag 1122223)
jedoch sehe ich hier das Problem, dass diese Methode nicht weiß, welcher Thread gerade fertig geworden ist (dann könnte sie über eine simple Get-Funktion die Rückgabewerte holen und ins Hauptprogramm bringen).

Du kannst im OnTerminate auf den Parameter Sender zurückgreifen, der dir die Instanz des gerade beendeten Threads liefert. Mit is und as kannst du dann auf deine speziellen Thread-Klasse zugreifen.

Oder du verwendest pro Thread-Instanz eine andere Event-Methode.

Hannes91 6. Sep 2011 21:06

AW: Rückgabewert von Threads
 
Lieber Herr Raabe,

vielen Dank für Ihre Ideen; die helfen mir weiter. Da habe ich wohl den Wald vor lauter Bäumen nicht gesehen :wink:!

Einen schönen Abend noch

Hannes

Hannes91 7. Sep 2011 11:50

AW: Rückgabewert von Threads
 
Hallo zusammen,

kaum hatte ich mir gestern Abend die Ideen von Betrag #2 zu Herzen genommen, ergab sich postwendend ein zweites Problem in diesem Kontext.

In einer Schleife
Delphi-Quellcode:
for i := 0 to iBloecke - 1
erzeuge ich bei jedem Durchlauf einen Thread (mithilfe der Klasse TThread), sofern die maximale Anzahl nicht überschritten wird (hier: 4). Diese erhalten, wie eingangs erwähnt, ihre Aufträge übermittelt und beginnen unverzüglich mit der Berechnung.
Sofern alle "Slots" belegt sind, sprich max. Anzahl an Threads erreicht ist, müsste das Hauptprogramm logischerweise in der Schleife warten, bis die Threads wieder geschlossen sind. Im OnTerminate lasse ich mir vorher die Ergebnisse sichern.
  • Wäre es hier möglich,
    Delphi-Quellcode:
    Waitformultipleobjects(length(lpHandles), @lpHandles[0], true, INFINITE);
    zu nehmen?
  • Könnte es bei "kurzen" Aufträgen zu Problemen kommen, dass der Thread schon vor Aufruf von
    Delphi-Quellcode:
    waitformultipleobjects
    beendet ist, welcher erst nach Start der max. Anzahl an Threads bei
    Delphi-Quellcode:
    (i mod iThreads = iThreads - 1) or (i = iBloecke - 1)
    erfolgt?
  • Wie ist die zeitliche Reihenfolge - Ende von Execute --> OnTerminate(Aufruf einer Methode) --> bis hier wartet
    Delphi-Quellcode:
    waitfor...
    ?
  • Wer muss den Thread wie schließen / schließt er sich doch selbst?

Ich hoffe doch inständig, dass ihr mir da etwas Licht ins Dunkle bringen könnt. :gruebel:

Liebe Grüße

Hannes

grl 7. Sep 2011 12:27

AW: Rückgabewert von Threads
 
Ich gehe hier gern einen anderen Weg:

Im Haupt-Thread lege ich eine Struktur an, in der die Ergebnisse der Threads gespeichert werden können (z.B. ein Array of Record).
Diese Struktur schütze ich über eine CriticalSection.

Der Thread schreibt seine Ergebnisse in diese Struktur und sendet dann eine Message an den Hauptthread, daß da was zu tun ist.
Dann muss nur noch der Message-Handler des Hauptthread auf diese Message reagieren und gut ists

Vorteil dieser Methode ist, daß nie jemand nach etwas pollen muss.

Gruß
Luggi

himitsu 7. Sep 2011 13:27

AW: Rückgabewert von Threads
 
Man könnte aber auch Message+CS weglassen und von den Threads aus über Synchronize auf diese Struktur zugreifen.
Der Hauptthread braucht da nichts abzusichern.

- wenn man statt dem Array eine TList nimmt, dann hat man eine gute Stelle, wo der Hauptthread dann auf die Änderungen reagiert.

Jumpy 7. Sep 2011 13:38

AW: Rückgabewert von Threads
 
Geht es dir denn in deiner Frage nur um die Ergebnissweitergabe an den Hauptthread, oder geht es auch darum, wieder neue Threads zu erzeugen, wenn die Zahle der Nebenthreads unter vier sinkt?

Hannes91 7. Sep 2011 13:47

AW: Rückgabewert von Threads
 
@Jumpy: Es sollen alle Threads beendet und die Ergebnisse abgespeichert werden, bevor neue Aufgaben verteilt und somit neue Threads bis zur max. Anzahl gestartet werden.

Nach wie vor scheinen meine Ideen eher zusammengewürfelt und wenig optimal zu sein.

Ach ja: Habs gerade mal mit
Delphi-Quellcode:
waitformultipleobjects
probiert, jedoch scheint der zugehörige fertige Thread nicht mitzuteilen, dass er fertig ist!?

Jumpy 7. Sep 2011 14:08

AW: Rückgabewert von Threads
 
Wie wäre es mit einem Counter? Ich zietiere mal aus diesem Delphi-Treff-Tutorial:

Zitat:

...Und hier wird es nun spannend. Nachdem die Arrays noch einmal neu gefüllt werden, wird ein interner Thread-Zähler auf 3 gesetzt. Dann werden die Threads gestartet:
Code:
with TBubbleSort.Create(BubbleSortBox, BubbleSortArray) do
  OnTerminate := ThreadDone;
Durch den Aufruf des Konstruktors Create wird auch automatisch die Execute-Methode aufgerufen, so dass der Thread startet. Außerdem wird dem Thread hier noch mitgeteilt, dass er auf das OnTerminate-Ereignis mit dem Ausführen der Methode "ThreadDone" reagieren soll. OnTerminate wird ausgelöst, sobald ein Thread fertig abgelaufen ist.
Nun laufen die Threads also, und in der Variablen ThreadsRunning steht, wie viele es sind. Ist ein Thread fertig, wird der Wert in ThreadDone um 1 reduziert. Sind alle Threads mit dem Sortieren am Ende angekommen, ist die Variable 0, und der Start-Button wird wieder verfügbar gemacht.
Ich bin bei Threads auch noch recht unerfahren, aber kann man nicht in deinem fall nach der Schleife, die die Threads erzeugt eine neue "Warteschleife" starten, die solange läuft (und nix macht) bis der Counter auf 0 steht? Oder die wie im Bsp. im OnTerminate eines Threads ausgeführte-Funktion veringert den Counter und schaut ob er schon null ist (also der letzte Thread fertig) und startet dann eine neue Prozedur, mit der es weitergeht und die die gesammelten Werte weiterverarbeitet...

patti 7. Sep 2011 14:23

AW: Rückgabewert von Threads
 
Der Vorschlag von Jumpy geht in die Richtung, was in Java unter dem Namen "CountDownLatch" bekannt ist. Das ist eine Klasse, deren Instanzen mit einem bestimmten Wert initialisiert werden. Jeder Thread kann diesen Wert dann (z.B. nach Abschluss der Arbeit) um 1 verringern. Im Haupt-Thread genügt dann ein Aufruf der Methode "await". Dieser Aufruf blockiert, bis der Wert des Latches 0 ist. Wenn dieser Mechanismus mehr als einmal benötigt wird, wird stattdessen eine (Cyclic)Barrier verwendet.

Leider weiß ich nicht, was Delphi da von Haus aus kennt, aber vielleicht helfen dir die Stichworte Latch und Barrier ja schonmal weiter.

lg


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:51 Uhr.
Seite 1 von 2  1 2   

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