AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte ThreadPool 1.0.9 für Delphi 2010-XE
Thema durchsuchen
Ansicht
Themen-Optionen

ThreadPool 1.0.9 für Delphi 2010-XE

Ein Thema von WladiD · begonnen am 14. Dez 2010 · letzter Beitrag vom 20. Okt 2015
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
WladiD
Registriert seit: 27. Jan 2006
Nachdem ich vergeblich nach einem Open-Source Thread-Pool für Delphi gesucht habe, welches meine Bedürfnisse abdeckt, musste ich mich dafür entschließen, einen eigenen zu schreiben. Diesen möchte ich euch hier vorstellen.

Vereinfacht kann man die Funktionsweise des ThreadPools wie folgt beschreiben:

Man verbindet sich aus einem beliebigen Thread mit dem spezifischen Manager (welcher ebenfalls ein eigenständiger Thread ist) und übergibt ihm eine Aufgabe. Der Manager übergibt die Aufgabe an einen neuen bzw. schlafenden Arbeiter oder packt sie auf die Warteliste, wenn bestimmte Grenzwerte es nicht zulassen die Aufgabe sofort abzuarbeiten. Der Arbeiter nimmt sich der Aufgabe an, arbeitet sie parallel ab und meldet sich über synchronisierte Ereignisse, wenn er fertig ist. Hat der Manager noch weitere Aufgaben anliegen, so bekommt der Arbeiter sofort den Nächsten. Sind alle Aufträge abgearbeitet, so kann der Manager eine bestimmte anzahl an Arbeitern schlafen legen (SpareWorkersCount) und die restlichen Arbeiter werden terminiert.


Hauptmerkmale
  • Manager und Arbeiter sind eigenständige Threads

  • Ein spezifischer Pool wird von den Basis-Klassen TPoolManager, TPoolWorker und TPoolTask abgeleitet, wobei nur wenige Methoden mit "Leben" gefüllt werden müssen.

  • Für jeden abgeleiteten TPoolManager wird (nur) bei Bedarf eine eindeutige Instanz erstellt (verborgenes Singleton pattern)

  • Die genaue Instanz eines spezifischen Managers ist unbekannt und muss über eine Verbindung mittels TMyPoolManager.Connect oder TMyPoolManager.Bind ermittelt werden

  • Der Manager erstellt die Arbeiter gemäß der Auftragslage dynamisch unter berücksichtigung einer definierbaren Obergrenze (TMyPoolManager.ConcurrentWorkersCount)

  • Die Arbeiter-Threads werden wiederverwendet. Das heißt, ist ein Arbeiter fertig und es liegen weitere Aufträge an, so bekommt er sofort den Nächsten.

  • Anzahl an schlafenden Arbeitern kann über TMyPoolManager.SpareWorkersCount definiert werden

  • Aufträge können einen Eigentümer haben

  • Für jeden Eigentümer können Event-Handler an die Ereignisse OnTasksStatus und OnTasksComplete gebunden werden

  • Aufträge können gezielt abgebrochen werden, z.B nach dem Eigentümer (TMyPoolManager.CancelTasksByOwner)

  • Jeder Auftrag verfügt über die Basis-Ereignisse: OnStart, OnCancel, OnDone und kann um beliebige weitere ergänzt werden

  • Aufträge können priorisiert werden

  • Der Manager unterstützt den Demand-Mode: D.h. er beendet sich selbst, wenn keine Aufträge anliegen und keine Arbeiter auf Vorrat gehalten werden müssen.

  • Alle instanzierten Thread-Pools (Manager und Arbeiter) können mit einer einzelnen Anweisung (z.B. bei Programmende) sauber terminiert werden: TPoolManager.TerminateAllRunningPools

  • Die Freigabe eines zuvor registrierten Eigentümer kann an alle Thread-Pools mittels TPoolManager.DispatchOwnerDestroyed übermittelt werden

  • Dynamsiche Anpassung von gleichzeitigen und auf Vorrat zu haltenden Arbeitern an das Ziel-System mittels TMyPoolManager.ConcurrentWorkersCountPerCPU und TMyPoolManager.SpareWorkersCountPerCPU

  • Last but not least: Kein Polling.
    Die Manager und Arbeiter lauschen mittels WaitFor(INFINITE) an ihren Hauptsignalen, dadurch wird kostbare Rechnerkapazität nicht sinnlos vergeudet.


Download

Damit ich das Archiv nicht bei jedem Update hier aktualisieren muss, verlinke ich am liebsten zur Projektseite bei SourceForge:

ThreadPool for Delphi (Download | Git-Repository)

Das Archiv enthält bereits zwei ausführliche Beispiele (auch in kompilierter Form), sodass man sowohl die Implementierung eines spezialisierten Thread-Pools nachvollziehen kann als auch dessen Verwendung.

Voraussetzung

Die Unit ist ab Delphi 2010 lauffähig.

Lizenz

Wie ich in der Einleitung geschrieben hatte, suchte ich nach einer Open-Source Lösung, die es nicht gab. Aus diesem Grunde stelle ich meine unter die MPL 1.1.

mfg

Geändert von WladiD (10. Mai 2011 um 11:41 Uhr) Grund: Neue Version / Geändertes Konzept
 
Bernerbaer
 
#2
  Alt 15. Dez 2010, 09:50
Ich habe mal versucht deine Beispiele zu kompilieren. Leider lässt sich ThreadPool unter meinem Delphi 2009 (alle aktuellen Updates eingespielt) nicht kompilieren.
Hier die Fehlermeldungen:
Code:
[DCC Fehler] ThreadPool.pas(183): E2123 PROCEDURE, FUNCTION, PROPERTY oder VAR erwartet
[DCC Fehler] ThreadPool.pas(184): E2169 Felddefinition nicht erlaubt nach Methoden oder Eigenschaften
[DCC Warnung] ThreadPool.pas(184): W1010 Methode 'Destroy' verbirgt virtuelle Methode vom Basistyp 'TThread'
[DCC Fehler] ThreadPool.pas(188): E2254 Die überladene Prozedur 'Create' muss mit der Direktive 'overload' gekennzeichnet sein
[DCC Fehler] ThreadPool.pas(189): E2254 Die überladene Prozedur 'Destroy' muss mit der Direktive 'overload' gekennzeichnet sein
[DCC Fehler] ThreadPool.pas(191): E2252 Es gibt bereits eine Methode 'Destroy' mit identischen Parametern
[DCC Fehler] ThreadPool.pas(390): E2123 PROCEDURE, FUNCTION, PROPERTY oder VAR erwartet
[DCC Warnung] ThreadPool.pas(390): W1010 Methode 'Destroy' verbirgt virtuelle Methode vom Basistyp 'TPoolThread'
[DCC Fehler] ThreadPool.pas(481): E2254 Die überladene Prozedur 'Destroy' muss mit der Direktive 'overload' gekennzeichnet sein
[DCC Fehler] ThreadPool.pas(483): E2252 Es gibt bereits eine Methode 'Destroy' mit identischen Parametern
[DCC Fehler] ThreadPool.pas(563): E2357 PROCEDURE, FUNCTION oder CONSTRUCTOR erwartet
[DCC Fehler] ThreadPool.pas(568): E2357 PROCEDURE, FUNCTION oder CONSTRUCTOR erwartet
[DCC Fehler] ThreadPool.pas(574): E2004 Bezeichner redefiniert: 'TPoolThread.Create'
[DCC Fehler] ThreadPool.pas(581): E2004 Bezeichner redefiniert: 'TPoolThread.Destroy'
[DCC Fehler] ThreadPool.pas(931): E2357 PROCEDURE, FUNCTION oder CONSTRUCTOR erwartet
[DCC Fehler] ThreadPool.pas(971): E2004 Bezeichner redefiniert: 'TPoolManager.Destroy'
[DCC Fehler] ThreadPool.pas(972): E2004 Bezeichner redefiniert: 'cc'
[DCC Fehler] ThreadPool.pas(183): E2065 Ungenügende Forward- oder External-Deklaration: 'TPoolThread.Create'
[DCC Fehler] ThreadPool.pas(184): E2065 Ungenügende Forward- oder External-Deklaration: 'TPoolThread.Destroy'
[DCC Fehler] ThreadPool.pas(390): E2065 Ungenügende Forward- oder External-Deklaration: 'TPoolManager.Destroy'
[DCC Fataler Fehler] PrimePoolForm.pas(6): F2063 Verwendete Unit '..\..\ThreadPool.pas' kann nicht compiliert werden
  Mit Zitat antworten Zitat
WladiD

 
Delphi 10.4 Sydney
 
#3
  Alt 15. Dez 2010, 10:38
Ich habe mal versucht deine Beispiele zu kompilieren. Leider lässt sich ThreadPool unter meinem Delphi 2009 (alle aktuellen Updates eingespielt) nicht kompilieren.
Hier die Fehlermeldungen:
Code:
[DCC Fehler] ThreadPool.pas(183): E2123 PROCEDURE, FUNCTION, PROPERTY oder VAR erwartet
[DCC Fehler] ThreadPool.pas(184): E2169 Felddefinition nicht erlaubt nach Methoden oder Eigenschaften
[DCC Warnung] ThreadPool.pas(184): W1010 Methode 'Destroy' verbirgt virtuelle Methode vom Basistyp 'TThread'
....
Hmm, Mist , ich dachte das einzig "exotische" was ich in ThreadPool benutzt hätte, wären die Closures. Es wurde mit Delphi 2010 entwickelt und den Meldungen nach zu urteilen, unterstützt D2009 keine verschachtelten Typen, also sowas in der Art:
Delphi-Quellcode:
   
TPoolThread = class(TThread)
type // verschachtelte Typen deklaration
  TLockList = TObjectList<TMultiReadExclusiveWriteSynchronizer>;
  TCriticalSectionList = TObjectList<TCriticalSection>;
private
public
 ...
end;
Oder die Unterstützung der Generics (benutze massiv Generics.Collections.TObjectList) ist noch schlechter als in 2010.

Ich persönlich bin von 2007 gleich auf 2010 gesprungen und habe nie 2009 verwendet, aber dass es Closures (anonyme Methoden) beherrscht wusste ich. Tja, dann muss ich die Anforderungen vorerst einfach mal hochschrauben.

Danke für das Feedback.
Waldemar Derr
  Mit Zitat antworten Zitat
taveuni

 
Delphi 11 Alexandria
 
#4
  Alt 15. Dez 2010, 10:47
Ich persönlich bin von 2007 gleich auf 2010 gesprungen und habe nie 2009 verwendet, aber dass es Closures (anonyme Methoden) beherrscht wusste ich. Tja, dann muss ich die Anforderungen vorerst einfach mal hochschrauben.
Danke für das Feedback.
Falls Du diesbezüglich was machst (2009 kompatibel), würdest Du auch in Betracht ziehen dies D2007 kompatibel (ohne Generics) zu machen?
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

 
Delphi 12 Athens
 
#5
  Alt 15. Dez 2010, 10:50
Dann müsste man aber auch auf die anonymen Methoden verzichten, von daher habe ich persönlich wenig Hoffnung
Detlef
  Mit Zitat antworten Zitat
WladiD

 
Delphi 10.4 Sydney
 
#6
  Alt 15. Dez 2010, 11:00
Falls Du diesbezüglich was machst (2009 kompatibel), würdest Du auch in Betracht ziehen dies D2007 kompatibel (ohne Generics) zu machen?
Generics wären nicht das Problem, vielmehr ist es die fehlende Unterstützung von Closures, die mir eine Umsetzung für < D2009 scheinbar unmöglich machen (zumindest nach dem aktuellen Konzept). Sicherlich, wäre es irgendwie machbar, aber das würde meinen Zeitrahmen sprengen.

Wer einmal die Vorteile von Closures erkannt hat, kann nicht mehr ohne...

Sorry.
Waldemar Derr
  Mit Zitat antworten Zitat
Zwoetzen

 
Delphi 2009 Professional
 
#7
  Alt 15. Dez 2010, 11:03
Wenn ich das richtig sehe, scheitert Delphi2009 am class constructor Create; bzw. class destructor Destroy; (die wohl für das Singleton-Pattern vorhanden sind?)

Ich habe mal testweise die Klassen-Konstruktoren und -Destruktoren auskommentiert, und sobald die vollständig gestrichen wurden, kompilierte Delphi2009 die Unit problemlos durch.
Meine Erfahrungen sagen auch, dass verschachtelte Typen (in D2009) kein Problem sein sollten, da ich die schon selbst mal verwendet hatte


Ansonsten hört sich der ThreadPool schonmal sehr interessant an, wäre schön, wenn ich die nutzen könnte
  Mit Zitat antworten Zitat
WladiD

 
Delphi 10.4 Sydney
 
#8
  Alt 15. Dez 2010, 11:13
Wenn ich das richtig sehe, scheitert Delphi2009 am class constructor Create; bzw. class destructor Destroy; (die wohl für das Singleton-Pattern vorhanden sind?)

Ich habe mal testweise die Klassen-Konstruktoren und -Destruktoren auskommentiert, und sobald die vollständig gestrichen wurden, kompilierte Delphi2009 die Unit problemlos durch.
Meine Erfahrungen sagen auch, dass verschachtelte Typen (in D2009) kein Problem sein sollten, da ich die schon selbst mal verwendet hatte


Ansonsten hört sich der ThreadPool schonmal sehr interessant an, wäre schön, wenn ich die nutzen könnte
Das ist doch was, womit ich etwas anfangen kann. Ich habe soeben die Hilfe durchforstet und finde kein Info, seit wann die die Klassenkonstruktoren/-destruktoren unterstützt werden. Werden Sie gänzlich nicht unterstützt, oder habe ich sie irgendwie falsch deklariert (z.B. muss im public/private)?

Ansonsten könnte man eine Compiler-Weiche einbauen und sich bei D2009 des initialization/finalization-Abschnitts bedienen.
Waldemar Derr
  Mit Zitat antworten Zitat
Zwoetzen

 
Delphi 2009 Professional
 
#9
  Alt 15. Dez 2010, 11:36
Laut Google sollen die Klassen-Konstruktoren erst ab Delphi2010 unterstützt werden


(Aus der Fehlermeldung
Zitat von DCC Fehler:
E2123 PROCEDURE, FUNCTION, PROPERTY oder VAR erwartet
würde ich auch schließen, dass D2009 allgemein kein constructor bzw. destructor nach einem class erwartet. Habe trotzdem mal die verschiedenen Sichtbarkeiten durchprobiert: Wie zu erwarten ohne Erfolg )
  Mit Zitat antworten Zitat
WladiD

 
Delphi 10.4 Sydney
 
#10
  Alt 15. Dez 2010, 11:46
Laut Google sollen die Klassen-Konstruktoren erst ab Delphi2010 unterstützt werden


(Aus der Fehlermeldung
Zitat von DCC Fehler:
E2123 PROCEDURE, FUNCTION, PROPERTY oder VAR erwartet
würde ich auch schließen, dass D2009 allgemein kein constructor bzw. destructor nach einem class erwartet. Habe trotzdem mal die verschiedenen Sichtbarkeiten durchprobiert: Wie zu erwarten ohne Erfolg )
Alles klar Zwoetzen,

danke für die Information (war zu faul zum googeln ), werde demnächst (bin grad an was anderem dran) die erwähnte Compiler-Weiche einbauen und mich hier wieder melden.
Waldemar Derr
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:57 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