MessageRequester aus einem Thread zu starten führt auch zu Problemen.
Um aus den Thread eine Userabfrage auszuführen habe ich hier ein SendEvent(...)
http://www.purebasic.fr/german/viewtopi ... =sendevent
Thread-Pool - Das angegebene 'Thread' ist null
Re: Thread-Pool - Das angegebene 'Thread' ist null
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Re: Thread-Pool - Das angegebene 'Thread' ist null
Danke!
Ja, das habe ich übersehen.
Danke auch für SendEvent().
Das sieht gut aus.
Da ich aber ohnehin schon PostEvent() verwende und der MessageRequester nur zum Testen da ist reicht das zumindest im Moment.
Wahrscheinlich kommen noch einige andere Themen auf mich zu sobald ich die Threads dann in einen Server einbauen will.
Ich war gerade dabei das ganze noch einmal mit echter Verarbeitung (statt #SleepTime) zu testen.
Dadurch konnte ich die Zeiten ohne Thread auch nicht mehr einfach nur vorhersagen.
Deswegen habe ich zum Testen noch ProzedurC() geschrieben.
Es ist schon erstaunlich was beim Herumspielen mit #ThreadQuantity und #JobQuantity heraus kommt.
Ja, das habe ich übersehen.
Danke auch für SendEvent().
Das sieht gut aus.
Da ich aber ohnehin schon PostEvent() verwende und der MessageRequester nur zum Testen da ist reicht das zumindest im Moment.
Wahrscheinlich kommen noch einige andere Themen auf mich zu sobald ich die Threads dann in einen Server einbauen will.
Ich war gerade dabei das ganze noch einmal mit echter Verarbeitung (statt #SleepTime) zu testen.
Dadurch konnte ich die Zeiten ohne Thread auch nicht mehr einfach nur vorhersagen.
Deswegen habe ich zum Testen noch ProzedurC() geschrieben.
Es ist schon erstaunlich was beim Herumspielen mit #ThreadQuantity und #JobQuantity heraus kommt.
Code: Alles auswählen
;-TOP
;CompilerIf #PB_Compiler_Thread
DisableDebugger
EnableExplicit
Global idThread.l, dwExitCode.l, x, TextGadgetText.s
Global StartTimeA, StartTimeB, StartTimeC, ElapsedTimeA, ElapsedTimeB, ElapsedTimeC
Define i, Event, Quit
; #ThreadQuantity = 64
; #JobQuantity = 256
#ThreadQuantity = 256
#JobQuantity = 1024
; #ThreadQuantity = 16
; #JobQuantity = 1024
; #ThreadQuantity = 16
; #JobQuantity = 1024
Enumeration #PB_Event_FirstCustomValue
#TestReady
#ThreadReady
#NewText
EndEnumeration
Global Dim ThreadHandles(#ThreadQuantity-1)
Macro Work
For i = 1 To 10
ys = Str(x*i)
ys = MD5Fingerprint(@ys, StringByteLength(ys))
ys = UCase(ys)
ys = MD5Fingerprint(@ys, StringByteLength(ys))
ys = LCase(ys)
ys = MD5Fingerprint(@ys, StringByteLength(ys))
Debug ys
Next
EndMacro
Procedure ThreadA()
Protected ys.s, yq.q, i
Repeat
Work ; Arbeitszeit generieren um die Threads gleichmäßig auszulasten - läuft auch ohne stabil
PostEvent(#ThreadReady)
SuspendThread_(GetCurrentThread_())
ForEver
EndProcedure
Procedure ThreadB()
Protected ys.s, yq.q, i
Work
PostEvent(#ThreadReady)
EndProcedure
Procedure ProzedurC()
Protected ys.s, yq.q, i
Work
x+1
;PostEvent(#ThreadReady) ist hier nicht nötig, da klar ist wann die Verarbeitung beendet ist
EndProcedure
Procedure Test()
Protected i, j
;- TestB
;Das sequentielle CreateThread_() wird als erstes getestet um sicher zu sein, dass keine Altlasten bremsen.
x = 0
TextGadgetText = "Teste sequentielles CreateThread_()"
PostEvent(#NewText)
Delay(100)
StartTimeB = ElapsedMilliseconds()
For i = 1 To #JobQuantity
Debug "B Job : "+Str(i)
CreateThread_(0, 0, @ThreadB(), 0, 0, @idThread)
Next i
Repeat: Until x = #JobQuantity
ElapsedTimeB = ElapsedMilliseconds()-StartTimeB
;- TestA
x = 0
TextGadgetText = "Teste vorbereitete Threads"
PostEvent(#NewText)
Delay(100)
StartTimeA = ElapsedMilliseconds()
For i = 1 To #JobQuantity
Debug "A Job : "+Str(i)
Repeat
For j = 0 To #ThreadQuantity-1
If ResumeThread_(ThreadHandles(j)) >0 : Break 2 : EndIf
Next j
ForEver
Next i
Repeat: Until x = #JobQuantity
ElapsedTimeA = ElapsedMilliseconds()-StartTimeA
; For j = 0 To #ThreadQuantity-1
; Repeat: Until TerminateThread_(ThreadHandles(j),@dwExitCode)
; Next j
;- TestC
x = 0
TextGadgetText = "Teste sequentiellen Aufruf von ProzedurC()"
PostEvent(#NewText)
Delay(100)
StartTimeC = ElapsedMilliseconds()
For i = 1 To #JobQuantity
Debug "C Job : "+Str(i)
ProzedurC()
Next i
Repeat: Until x = #JobQuantity
ElapsedTimeC = ElapsedMilliseconds()-StartTimeC
TextGadgetText = "Fertig!"
PostEvent(#NewText)
PostEvent(#TestReady)
EndProcedure
If OpenWindow(0, 100, 200, 200, 50, "Please wait")
TextGadget(1, 0, 20, 200, 30, "Vorbereitung ...", #PB_Text_Center)
For i = 0 To #ThreadQuantity-1 ; Threads vorbereiten
ThreadHandles(i) = CreateThread_(0, 0, @ThreadA(), 0, #CREATE_SUSPENDED, @idThread)
; #CREATE_SUSPENDED -> "Threads werden erzeugt - arbeiten aber noch nicht"
Next i
For i = 0 To #ThreadQuantity-1 ; überprüfen ob alle Threads startbereit sind
If ThreadHandles(i)
Repeat : Until SuspendThread_(ThreadHandles(i)) >0
ResumeThread_(ThreadHandles(i)) ; Suspend-Wert zurück setzen
EndIf
Next i
CreateThread_(0, 0, @Test(), 0, 0, @idThread)
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_CloseWindow
Quit = 1
Case #ThreadReady
x+1
Case #TestReady
If MessageRequester("Vorbereitete Threads gegenüber einfachem CreateThread_() gegenüber Aufruf von ProzedurC()", Str(ElapsedTimeA)+" zu "+Str(ElapsedTimeB)+" zu "+Str(ElapsedTimeC), #PB_MessageRequester_Ok)
Quit = 1
EndIf
Case #NewText
SetGadgetText(1, TextGadgetText)
EndSelect
Until Quit = 1
EndIf
; CompilerElse
; Debug "Bitte 'Thread-sicheren Exekutable erstellen' in den Compiler-Optionen auswählen."
; CompilerEndIf