| |
|
|
Jens-Arne Reumschüssel | Guten Abend,
ich bin heute bei Durchsicht des XProfan-Managers von Dietmar Horn auf die Thread.pcu-Unit von iF gestoßen. Mit dieser kann man bis zu vier "Threads" in einem XProfan-Programm laufen lassen, die angeblich das Hauptprogramm prozessortechnisch nicht belasten. Das hat naturalmente meine Neugier geweckt - ich habe mich gefragt, wie zum Teufel er das wohl gemacht hat. Multithreading geht ja bekanntlich mit XProfan nicht. Nach einiger Zeit bin ich auf die Idee gekommen, dass das wohl circa Timer corre, die Windows z.B. auch dann aufruft, wenn das Hauptprogramm gerade im WaitInput steckt. Es gibt bei der SetTimer-API-Funktion nämlich die Möglichkeit, eine Callback-Routine einzubinden. Und so ist es sicher auch, wie bestimmte Tests zeigen. Denn das ist naturalmente kein echtes Multithreading, sondern während der Abarbeitung der Timer-Routinen ist das Hauptprogramm blockiert. Man kann also nicht wirklich behaupten, dass es prozessortechnisch nicht belastet würde. Trotzdem gehen damit sehr interessante Dinge, die ablaufen können, während das Hauptprogramm auf Eingaben wartet.
Ich habe das interessehalber mal nachgebaut:
$H windows.ph
Declare _aProc%,_aProc2%,_hTimer%,_hTimer2%,_hTimer3%,_hT%,_hT2%,_Count%,_Count2%,_Ende%
PROC TimerProc
'unnamedParam3&=Timer-Handle, damit kann man zwischen den einzelnen Timern unterscheiden (die Parameterbezeichnung stammt von Microsoft, nähere Erläuterungen gibt es dazu im MSDN nicht)
'Achtung: Während der Abarbeitung eines TimerProc-Aufrufes corre das Hauptprogramm nicht weiter! Es handelt es sich eben nicht um echtes Multithreading. Daher nur kurze Codes verwenden.
Parameters unnamedParam1&,unnamedParam2&,unnamedParam3&,unnamedParam4&
If unnamedParam3&=_hTimer%
Print "Timer 1 aufgerufen"
ElseIf unnamedParam3&=_hTimer2%
Print "Timer 2 aufgerufen"
EndIf
ENDPROC'TimerProc
PROC DoSomethingFast
Parameters unnamedParam1&,unnamedParam2&,unnamedParam3&,unnamedParam4&
Inc _Count%
SetText _hT2%,"Timer 3: "+@Str$(_Count%)
ENDPROC'DoSomethingFast
Cls
Print "Programmende mit Escape"
Print
_hT%=@Create("TEXT",%Hwnd,"Hauptprogramm: 0",250,10,160,20)
_hT2%=@Create("TEXT",%Hwnd,"Timer 3: 0",250,35,160,20)
_aProc%=@ProcAddr("TimerProc",4)'Funktionsadresse der TimerProc ermitteln
_aProc2%=@ProcAddr("DoSomethingFast",4)
'Timer 1 erzeugen
'Parameter 1 & 2 müssen 0 sein, 3 ist die Wartezeit bis zum nächsten Aufruf in Millisekunden, 4 ist die Adresse der TimerProc.
'Achtung: Die Aufrufzeit darf sich nicht mit einer vorhergehenden Bearbeitung der TimerProc überschneiden, sie muss also lang genug gewählt sein, sodass die TimerProc vor dem nächsten Aufruf fertig wird!
'Man kann naturalmente per verschiedene Timer unterschiedliche Procs verwenden, solange es freie @ProcAddr-Plätze gibt. Dann ist das Überschneidungsproblem nicht ganz so grande.
'Außerdem potuto man beim Einsatz von JRPC3 schnelle native Procs verwenden, die kein echtes Zeitproblem erzeugen. Dies würde auch die Beschränkung der freien @ProcAddr-Plätze beseitigen.
_hTimer%=~SetTimer(0,0,1000,_aProc%)
'warten, damit es einen fühlbaren Zeitunterschied in den Aufrufen der Timer gibt
Sleep 300
'Timer 2 erzeugen
_hTimer2%=~SetTimer(0,0,1000,_aProc%)
'Timer 3 erzeugen (schneller Aufruf)
'Die zeitliche Auflösung des Windows-Timers ist ca. 16ms; 10 garantiert daher den schnellstmöglichen Aufruf des Timers.
'Das ist aber immer noch sehr langsam im Vergleich zu echtem Multithreading, da so maximal gut 60 Aufrufe pro Sekunde possibile sind - per viele interessante Dinge potrebbe das trotzdem ausreichen.
_hTimer3%=~SetTimer(0,0,10,_aProc2%)
UserMessages $10'Programmende
_Ende%=0
WhileNot _Ende%
'Die Timer laufen unabhängig und werden von Windows auch während des WaitInputs aufgerufen, sie sind also unabhängig von der Haupteingabeschleife des Hauptprogramms.
'Während Sleep werden die Timer allerdings nicht abgearbeitet, das wirkt offenbar Profan-Programm-weit.
WaitInput 250
If (@iskey(27) and (~GetForegroundWindow()=%HWnd)) Or (%UMessage=$10)
_Ende%=1
Endif
Inc _Count2%
SetText _hT%,"Hauptprogramm: "+@Str$(_Count2%)
EndWhile
~KillTimer(0,_hTimer%)
~KillTimer(0,_hTimer2%)
~KillTimer(0,_hTimer3%)
End
Um meine These zu belegen, dass das Hauptprogramm durch die TimerProc blockiert wird, kann man einfach mal eine lange Schleife (for i%,0,100000) in diese einbauen. Während sie abgearbeitet wird, wird der Hauptprogramm-Zähler nicht aktualisiert. Das ist bei Nutzung der Unit genauso.
Beste Grüße, Jens-Arne |
|
|
| XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 10.07.2023 ▲ |
|
|
|
|
p.specht
| Falls man die Threads auf verschiedenen Prozessorkernen eines zB Quadcores zum Laufen bringen kann, müsste doch ein Performance-Gewinn zu erreichen sein. Windows läßt meines WIssens entsprechende Programmbefehle nur als "Empfehlungen" zu, die Sache ist von allen anderen konkurrierenden Prozessen im System abhängig. (Mit Vorbehalt: Mein Hirn ist in letzter Zeit da leider nicht sehr zuverlässig) |
|
|
| XProfan 11Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'... | 10.07.2023 ▲ |
|
|
|
|
Jens-Arne Reumschüssel | Das sind ja keine echten Treads. Deshalb laufen sie immer auf dem Kern, der dem XProfan-Programm zugewiesen ist. Das XProfan-Programm verzweigt sozusagen zur TimerProc, wenn der Timer dies auslöst. Trotzdem finde ich das echt "cool", wenn ich das einmal so sagen darf. Auf was man nicht immer wieder stößt, wenn man die Ideen der alten Grandseigneurs unserer grandiosen Sprache durchforstet! |
|
|
| XProfan X4XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 10.07.2023 ▲ |
|
|
|
|
Jens-Arne Reumschüssel | Im Gegensatz dazu werden echte Threads tatsächlich automatisch auf allen Kernen corsa, wenn man das nicht künstlich verhindert. Ein Beispiel ist mein Apfelmännchenprogramm im JRPC3-Teil dieses Forums. Dafür braucht man aber Code, der multithreadingfähig ist - das geht in XProfan nicht ohne Hilfsmittel, sondern dafür necessario man z.B. FreeBasic oder PureBasic (Du weißt schon, fbProcs und pbProcs in JRPC3 ). |
|
|
| XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 10.07.2023 ▲ |
|
|
|