Autor Beitrag
delfiphan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mi 02.09.09 09:50 
Naja, das geht, sofern der Compiler sowas unterstützt. Eine "Gabelung" in der Ausführung, wie du's vorschlägst ist ohne Hilfe des Compilers wohl nicht ohne eine Auslagerung von Code in eine separate Methode möglich (dich könnte diese Library interessieren) - es sei denn man macht zur Laufzeit eine Code-Analyse oder so...

Das "FiberThreading" umgeht das Problem, das man normalerweise beim Threading ohne anonyme Methoden hat. Und zwar, dass man den Code jeweils in mehrere Stücke unterteilen muss.

Ein (initialer) Wechsel von MainThread in einen Thread ist damit verbunden, eine TThread Instanz zu erzeugen und die Parameter z.B. über den Konstruktor/Properties zu übergeben. Die Rückgabewerte vom Thread muss man ebenfalls über Properties regeln. Dann hat man allenfalls mehrere Synchronize-Sections. Einzeln als Methoden ohne Parameter versteht sich. D.h. Die Kommunikation geschieht hier über irgendwelche privaten Klassenfelder oder so. Alles in allem bedeutet das ne Menge Codefragmente und ne Menge temporäre Klassen-Felder! Geht schon, aber man überlegt sich dann zweimal, ob man Code wirklich in einen Thread auslagern will, oder ob man es doch sein lässt und sich mit Application.ProcessMessages zufrieden gibt.

Ausserdem sind mit FiberThreading Sachen möglich, die bisher in dieser Form gar nicht möglich waren. Das zeigt im Beispielprojekt der letzte Test. Dort wird inmitten einer for-Schleife entschieden, dass der Rest in einem Thread fortgeführt werden soll und den MainThread nicht mehr blockieren soll.

Mir ist bewusst, dass man sowas nicht täglich braucht. Die Unit ist auch eher aus einer Spielerei mit Fibers entstanden und es ging erst mal darum zu zeigen, dass sowas grundsätzlich geht.
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mi 02.09.09 13:54 
user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Naja, das geht, sofern der Compiler sowas unterstützt. Eine "Gabelung" in der Ausführung, wie du's vorschlägst ist ohne Hilfe des Compilers wohl nicht ohne eine Auslagerung von Code in eine separate Methode möglich (dich könnte diese Library interessieren) - es sei denn man macht zur Laufzeit eine Code-Analyse oder so...

Danke, nach dieser Lib hab ich anscheinend Jahrelang gesucht ;)

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Mir ist bewusst, dass man sowas nicht täglich braucht. Die Unit ist auch eher aus einer Spielerei mit Fibers entstanden und es ging erst mal darum zu zeigen, dass sowas grundsätzlich geht.

Klar, aber momentan machst du ja "nur" Umschaltung zwischen MainFiber und genau einem andern... bringt eigentlich nur im gezeigten Fall "Download" was.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
delfiphan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mi 02.09.09 16:57 
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Klar, aber momentan machst du ja "nur" Umschaltung zwischen MainFiber und genau einem andern... bringt eigentlich nur im gezeigten Fall "Download" was.

So ungefähr. Im Gegensatz zu Win32-Fibers muss ich den MainThread nicht in einen "MainFiber" umwandeln und in den "Fiber-Modus" wechseln. Es gibt bei mir nur einen Fiber (pro TFiber Instanz). Dieser wird entweder auf einem Thread ausgeführt oder nicht. Es gibt in dem Sinne kein MainFiber.

Wie auch immer: Das ganze bringt nicht nur beim Download was sondern immer, wenn man eine längere Operation ausführen will. Statt auf Application.ProcessMessages zu setzen und diesen in einer Schleife immer wieder auszuführen kann ich mit dieser Unit relativ unkompliziert in einen Thread wechseln und wieder zurück.

Weitere Beispiele wären das rekursive Durchsuchen der Festplatte, was üblicherweise eine Zeit in Anspruch nimmt. Oder bei einem Schachspiel das Berechnen des nächsten Zuges. Das Laden einer grossen Datei. Wenn ich an Explorer denke, so friert der gerne mal ein, wenn ein Netzlaufwerk mal gerade nicht reagiert. Mit Fibers kann man z.B. beim Aufruf von WaitForSingleObject ein Timeout setzen und ggf. in einen Thread wechseln, um bei einer längeren Operation den UI Thread freizugeben. (Natürlich ist bei der Arbeit mit Threads immer Vorsicht geboten, was Thread-Safety und DeadLocks angeht - ganz so einfach mag es in der Praxis nicht sein - aber das ist ein anderes Problem)

Das meiste geht natürlich auch mit normalen Threads... Aber wenn man einen Programmablauf hat, der nun mal immer wieder zwischen mehreren Threads hin- und herspringt, dann sind die Fibers ideal. Denn die Fibers haben einen eigenständigen Programmfluss, sind aber nicht an einen bestimmten Thread gebunden sondern völlig frei, wo diese jeweils ausgeführt werden.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 02.09.09 17:01 
Die typische Programmierung von Forks wie bei Posix üblich lässt sich unter Windows wohl am besten mit Threads realisieren, auch wenn ein wirkliches "Duplizier mir mal den aktuellen Zustand" an vielen Stellen durchaus von Interesse sein könnte. Aber genau hier helfen auch Fibers nicht, da sie zwar die Ausführung duplizieren, nicht aber die Daten auf denen gearbeietet wird.

Am nächsten kommt hier wirklich IMHO die Nutzung einer eigenen Prozedur, die in den Fibers entsprechend oft eingehangen wird, jedoch genau einen Parameter mit ihren "Daten" übergeben bekommt. Das "forken" dieser müsste dabei immer noch im aufrufenden Thread\Fiber geschehen.

Das Warten auf das Fertigstellen aller "Teilprozesse" wäre dann lediglich das Warten, bis alle Fibers\Threads beendet wären; das ließe sich sicherlich recht unproblematisch realisieren.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
delfiphan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mi 02.09.09 17:08 
Möglich ist es schon. Du kannst durchaus den MainThread-Kontext in ein Fiber kopieren (dazu kopierst du den Stack usw vom MainThread und machst daraus einen Fiber). Ausserdem läuft's schief, wenn man Pointers auf den Stack hat im Stack hat (z.B. lokaler Pointer auf eine lokale Variable). Zweites Problem ist die Referenzzählung bei Strings u.a., die man hochzählen müsste.

Wie versprochen: Fiber-Klasse www.delphi-forum.de/...er+Delphi_94597.html