Seite 2 von 2

Verfasst: 28.02.2005 23:58
von Team100
...man braucht nur ein Delay(1) in die Thread-Loop einbauen, dann
scheint es zu gehen......

Code: Alles auswählen

Procedure.l Thread() 
  Repeat 
    ThreadVar+1 
    Delay(1)  
ForEver 
EndProcedure
Irgendwie ist mir aber die Sache unheimlich.

Was nun wenn durch ein völlig anderes Programm die Prozessor-
leistung "gefressen" wird, eventuell noch durch hochgesetzte Priorität ?

Wird dann das Threadprogramm wiederum hängen bleiben? /:->

Oder läuft es trotzdem und ist delay(1) einfach eine Notwendigkeit ?
Dann gehört die Hilfe dringend ergänzt .....

@jear ... Wie zuverlässig ist denn diese Abstimmung unter unterschiedlichen OS (Windows)
und auf unterschiedlichen CPUs?

Cu von Team100

Verfasst: 01.03.2005 00:00
von junky
@jear
Ja das ist mir auch bewusst - und die Antwort auf deinen Post, der ja durchaus ein Stück weiter geholfen hat, war auch nit bös gemeint. Bin nur langsam echt mit den Nerven am Ende, durchforste mein Projekt nun schon seit 3 Tagen nach irgendwelchen ominösen Fehlern und es geht als nit voran...

Nur, es ist wirklich wichtig, dass der Thread in unserem Fall die Variable mehr als 100 Mal die Sekunde inkrementiert - und zwar in vollen Durchläufen (die Variable symbolisiert ja nur eine Programmteil - also noch ne extra Schleife oder so gilt nicht ;) ).

Wie bekomm ich das geregelt? - Oder muss ich mich da nach etwas total neuem umschauen? - Meint ihr, das OS selbst schießt den Thread ab, wenn kein Delay() drin ist? aber wenn JA, wieso arbeitet dann z.B. mein Code oben OHNE Debugger einwandfrei?

Edit:
stimme übrigends mit Team100 überein, also mit seinen Fragen... :allright:

Verfasst: 01.03.2005 00:35
von jear
Da muss ich aber ausholen ...
Ein Thread macht normalerweise irgendeine Tätigkeit im Hintergrund und, wenn er fertig ist, dann macht er Schluss.
Nun will man ja sehen, ob der Thread läuft oder man ist an Zwischenergebnissen interessiert. Also schaut man in Variablen hinein, die im Thread laufend verändert werden. Man kann auch über solche Variablen ein echtes Handshaking aufbauen. ZB. nur, wenn im GUI der Anwendung eine Variable ausgelesen und zu Null gesetzt worden ist, schreibt der Thread wieder etwas hinein. Inzwischen sammelt er seine Ergebnisse in lokalen Variablen.
Auf diesem Wege (es gibt auch andere) kann man eine sichere Threadkonstruktion aufbauen.
Strings darf man nicht verwenden, besonders nicht in HT-Systemen, denn PB verwaltet alle Strings in einem Pool und nicht für jeden Prozessor getrennt. Aber nullterminierte Byte-Array tun es ja auch.

Der Debugger ist überhaupt nicht Thread-fest, egal was man anstellt.
Da muss man sich im GUI für die Testphase einfach entsprechende Ausgabemöglichkeiten in Gadgets schaffen, wie es im Beispiel gezeigt ist.

@junky : nun zu Deiner speziellen Frage. Wenn "draußen" nichts von den Ergebnissen des Thread angezeigt werden soll, dann kann dieser natürlich frei und so schnell es geht laufen. Wenn kein Delay eingebaut ist, dann regelt das OS eben per Zeitscheiben die Verteilung der CPU-Zeit an die Prozesse. Das Delay() ist eben ein probates Mittel, die beiden quasi-zeitgleich ablaufenden Programmteile aufeinander abzustimmen.

@Team100 : Wir haben eine größere Anwendung in Arbeit, die, nachdem wir alle diese Dinge herausgefunden und beachtet haben, in dieser Hinsicht stabil läuft. Unsere Betatester (weltweit) haben uns wenigstens bisher keinerlei Probleme dazu auf den Tisch gepackt.

Hier noch ein bischen Code zum spielen. Er läuft nur als Exe, ist aber schon fast ein neuer Benchmark. Bei mir (P4 3.0HT) liegt die beobachtete minimale Zeit pro Run bei 7.360 Sekunden. Ein Run ist eine Long rauf und runter, also > 50 Mio Durchläufe pro Sekunde.
Das Delay(0) hat bei meinem System einen beruhigenden Effekt und drückt die Minimalzeit! Win ist nun mal kein Echtzeit-BS !
Durch Erzeugen von CPU-Last kann man schön sehen, wie sich das Verhalten der Thread-Konstruktion ändert.

Code: Alles auswählen

; Thread-Test 2 by jear 0500301
Global HVar.l, runs.l,  dt.f

DefType.f dtmax , dtmin

Procedure.l Thread()
  Protected ix.l, t0.l
  t0 = GetTickCount_()
  Repeat
    ix + 1
    If ix = 0 : runs + 1 : dt = (GetTickCount_() - t0)/1000 : t0 = GetTickCount_() : EndIf 
    If HVar = 0 : HVar = ix : Delay(0): EndIf 
  ForEver 
EndProcedure  

If OpenWindow(0, 300, 300, 200, 200, #PB_Window_SystemMenu, "Thread-Test") 
  If CreateGadgetList(WindowID())
    TextGadget(1, 20, 20, 50, 12, "WinEvent")
    TextGadget(2, 20, 40, 50, 12, "Runs")
    TextGadget(3, 20, 60, 50, 12, "ThreadVar")
    TextGadget(4, 20, 80, 50, 12, "TDiff (s)")
    TextGadget(5, 20, 100, 50, 12, "TDiff min")
    TextGadget(6, 20, 120, 50, 12, "TDiff max") 
    TextGadget(7, 90, 20, 80, 12, "0",#PB_Text_Right)
    TextGadget(8, 90, 40, 80, 12, "0",#PB_Text_Right)
    TextGadget(9, 90, 60, 80, 12, "0",#PB_Text_Right)
    TextGadget(10, 90, 80, 80, 12, "0.000",#PB_Text_Right)
    TextGadget(11, 90, 100, 80, 12, "0.000",#PB_Text_Right)
    TextGadget(12, 90, 120, 80, 12, "0.000",#PB_Text_Right) 
    CloseGadgetList()
  EndIf
  dtmin = 999.000
  CreateThread(@Thread(), 0)
  SetTimer_(WindowID(),1,100,0)
  Repeat 
    EventID.l = WaitWindowEvent() 
    SetGadgetText(7, Str(EventID))
    If EventID = #WM_TIMER
      SetGadgetText(8, Str(runs))
      SetGadgetText(9, Str(HVar))
      SetGadgetText(10, StrF(dt,3))
      If dt > 0.0 And dt < dtmin : dtmin = dt : SetGadgetText(11, StrF(dtmin,3)) : EndIf
      If dt > dtmax : dtmax = dt : SetGadgetText(12, StrF(dtmax,3)) : EndIf 
      HVar = 0 ; Flag-Funktion
      SetTimer_(WindowID(),1,100,0)
    ElseIf EventID = #PB_Event_CloseWindow 
      Quit = 1 
    EndIf  
  Until Quit = 1  
EndIf 
KillTimer_(WindowID(),1)
End 

Verfasst: 01.03.2005 14:06
von Team100
@jear

Danke für die kompetente Antwort. :allright:

Das sieht sehr vernünftig aus und ist eine solide Basis für eigene
Entwicklungen. Der Trick mit Delay(0) ist sehr gut. :D

Vielen Dank

Cu von Team100

Verfasst: 01.03.2005 18:15
von junky
ja ich schließe mich meinem Vorredner ma an ;)
@ Danke nochmal an alle Antworten!

@jear - hast mir echt weiter geholfen (denke ich... werd jetz noch ein bisschen Testen gehen, aber der Tipp mit dem Delay(0) is wirklich gut). Was mich nur sehr verwundert, ist der Debugger :? - muss ich mir echt was einfallen lassen, z.B. beim Entwickeln des restlichen Programms diese sehr rechenintensiven Threads rausnehmen...