SetGadgetText und SetGadgetState sehr CPU lastig?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von Micha122 »

Hallo!
In meinem Programm lese ich aus einer Textdatei Datensätze und und schreibe diese in eine SQL-DB.
Ging selbst bei 300000 Datensätzen recht fix, bis ich auf die Idee kam ein Fortschrittsfenster einzubauen.

Erst nachdem ich die Gadgets nur alle 100 Datensätze aktualisierte war das Ergebnis einigermaßen OK.
Trotz der Verzögerung von "alle 100 Datensätze" ist mir jedoch aufgefallen, das nur die Gadget Befehle 10% der Programmausführungszeit benötigen.

Hier ein kleines Beispiel zum veranschaulichen:

Code: Alles auswählen

anzahl=300000
; Fenster und Gadgets öffnen
  Window_0 = OpenWindow(#PB_Any, 0, 0, 740, 270, "Daten importieren", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
  ProgressBar_0 = ProgressBarGadget(#PB_Any, 200, 20, 290, 30, 0, anzahl, #PB_ProgressBar_Smooth)
  Text_0 = TextGadget(#PB_Any, 200, 50, 290, 20, "", #PB_Text_Center)
  Text_1 = TextGadget(#PB_Any, 20, 90, 110, 20, "Vorlaufdaten:", #PB_Text_Right)
  Text_2 = TextGadget(#PB_Any, 10, 120, 120, 25, "Hauptdaten A:", #PB_Text_Right)
  Text_3 = TextGadget(#PB_Any, 20, 150, 110, 20, "Hauptdaten B:", #PB_Text_Right)
  Text_4 = TextGadget(#PB_Any, 20, 180, 110, 20, "Langtexte:", #PB_Text_Right)
  Text_5 = TextGadget(#PB_Any, 140, 90, 220, 20, "")
  Text_6 = TextGadget(#PB_Any, 140, 120, 200, 20, "")
  Text_7 = TextGadget(#PB_Any, 140, 150, 230, 20, "")
  Text_8 = TextGadget(#PB_Any, 140, 180, 230, 20, "")
  Button_0 = ButtonGadget(#PB_Any, 310, 230, 100, 25, "Abbruch")
  WaitWindowEvent() 
  
  ;Code ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  While ee<100000
    a+1
    b+1
    c+1
    ee+1
   ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   
   
   
   
   verzoegerung+1 
   If verzoegerung=20
    ;Gadgets aktualisieren
          SetGadgetText(Text_0,Str(a+b+c)+" von "+Str(anzahl))
          SetGadgetState(ProgressBar_0,a+b+c)
          SetGadgetText(Text_6,Str(a)+" von 100000")
          SetGadgetText(Text_8,Str(b)+" von 100000")
          SetGadgetText(Text_7,Str(c)+" von 100000")
          WaitWindowEvent()
 ;Abbruch Button abfragen
          If EventGadget()=Button_0
            result=MessageRequester("Achtung!","Möchten Sie wirklich abbrechen?",#PB_MessageRequester_YesNo)
            If result=#PB_MessageRequester_Yes          
            End      
          EndIf
        EndIf
        verzoegerung=0
      EndIf
  Wend
Im Beispiel werden die SetGadget Befehle nur alle 20 mal ausgeführt, da sonst sogar dieser simple Code bei mir mehrere Minuten dauert.

Oder mache ich da vielleicht was falsch?? :oops:

Gruß, Michael
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8838
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von NicTheQuick »

Wo ist denn hier eine korrekte Eventschleife? Ich sehe nur ein 'WaitWindowEvent()' vor der Schleife. Und innerhalb alle 20 Durchläufe ein 'EventGadget()' ohne Überprüfung auf ein vorher eingehendes '#PB_Event_Gadget'-Event.

Ansonsten ist es aber normal, dass tausende Gadget-Aktualisierungen pro Sekunde alles verlangsamen, weil diese Aktualisierungen wiederum Events erzeugen, die erst abgearbeitet werden müssen. Deswegen macht man das z.B. mit Timern.
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Re: SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von Micha122 »

Wozu eine Eventschleife? Das Fenster dient nur zur Ausgabe, mit Ausnahme des "Abbruch" Button.

Wie funktioniert das mit Timern?

Gruß
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von STARGÅTE »

Also, das Auge kann gerade mal ~24 Einzelbilder pro Sekunde wahrnehmen, es ist also quatsch hier innerhalb weinger Sekunden 10000 änderungen an einem Gadget durchknallen zu lassen.

Ein WaitWindowEvent() hast du ja in deiner schleife unten drin, aber du prüfst dort nicht, welches Event stattfand.
Außerdem heißt WaitWindowEvent() dass er trotzdem eine gewisse Zeit wartet.
Dort könntest du zB nur WindowEvent schreiben.

Ansonsten kannst du mit AddWindowTimer() einen Timer erstellen, der alle 50ms (reicht aus) die Gadgets aktualisiert.
Der Timer wird dann wie andere Events in der Eventschleife abgefragt.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von Josh »

NicTheQuick hat geschrieben:Ich sehe nur ein 'WaitWindowEvent()' vor der Schleife.
Ich seh sogar zwei WaitWindowEvent() :D

@Micha122
Gewöhne dir saubere Einrückungen an. So wie du deinen Code schreibst, verlierst du schnell den Überblick und einer der dir Hilfe leisten soll, hat wahrscheinlich wenig Bock erst deinen Code ordentlich zu formatieren.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8838
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von NicTheQuick »

Eine Eventschleife braucht man IMMER, wenn man mit Fenstern arbeitet. Weil alles mögliche Events liefert, die nur abgearbeitet werden, wenn man auch '(Wait)WindowEvent()' aufruft. Tut man das nicht, denkt Windows irgendwann, dass das Fenster nicht mehr reagiert und schreibt "(keine Rückmeldung)" in die Titelleiste.
Events kommen schon dann, wenn man nur die Maus über das Fenster bewegt, seine Größe ändern oder es versucht oder Gadgets aktualisiert, wie z.B. bei 'SetGadgetText()'.

Starte den Code, bewege die Maus oder mach sonst irgendwas, und du siehst, was ich meine.

Code: Alles auswählen

Define event.i

If OpenWindow(0, 0, 0, 400, 400, "Eventtest")
	Repeat
		event = WaitWindowEvent()
		Debug "Event: " + event
	Until event = #PB_Event_CloseWindow
EndIf
Edit:
Josh hat geschrieben:
NicTheQuick hat geschrieben:Ich sehe nur ein 'WaitWindowEvent()' vor der Schleife.
Ich seh sogar zwei WaitWindowEvent() :D
Oha, tatsächlich. ^^
Benutzeravatar
Kiffi
Beiträge: 10725
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von Kiffi »

hier mal ein Beispiel mit einem Thread und PostEvents:

Code: Alles auswählen

Enumeration #PB_Event_FirstCustomValue
  #EventBeginProcessing
  #EventUpdateStatusbar
  #EventProcessingFinished
EndEnumeration

EnableExplicit

Global ProgressBarValue

Procedure myThread(DummyVar)
  
  Protected  Counter
  
  PostEvent(#EventBeginProcessing)
  
  For Counter = 0 To 100
    ProgressBarValue = Counter
    PostEvent(#EventUpdateStatusbar)
    Delay(100)
  Next
  
  PostEvent(#EventProcessingFinished)
  
EndProcedure

#myWindow=0
#myButton=0
#myProgressbar=1

OpenWindow(#myWindow, #PB_Ignore, #PB_Ignore, 285, 88, "Worker")
ButtonGadget(#myButton, 10, 5, 265, 35, "Starte lang dauernden Prozess")
ProgressBarGadget(#myProgressbar, 10, 50, 265, 20, 0, 100)

Define Thread

Repeat
  
  Select WaitWindowEvent()
      
    Case #PB_Event_Gadget
      
      Select EventGadget()
          
        Case #myButton
          
          Thread = CreateThread(@myThread(), 42)
          
      EndSelect
      
    Case #EventBeginProcessing
      
      DisableGadget(#myButton, #True)
      
    Case #EventUpdateStatusbar
      
      SetGadgetState(#myProgressbar, ProgressBarValue)
      
    Case #EventProcessingFinished
      
      DisableGadget(#myButton, #False)
      
    Case #PB_Event_CloseWindow
      
      If Not IsThread(Thread)
        Break 
      EndIf
      
  EndSelect
  
ForEver
Grüße ... Kiffi
a²+b²=mc²
Kevin
Beiträge: 236
Registriert: 11.06.2007 12:55

Re: SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von Kevin »

es gibt noch eine einfachere Lösung:

Code: Alles auswählen

anzahl=300000000
; Fenster und Gadgets öffnen
Window_0 = OpenWindow(#PB_Any, 0, 0, 740, 270, "Daten importieren", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
ProgressBar_0 = ProgressBarGadget(#PB_Any, 200, 20, 290, 30, 0, anzahl, #PB_ProgressBar_Smooth)
Text_0 = TextGadget(#PB_Any, 200, 50, 290, 20, "", #PB_Text_Center)
Text_1 = TextGadget(#PB_Any, 20, 90, 110, 20, "Vorlaufdaten:", #PB_Text_Right)
Text_2 = TextGadget(#PB_Any, 10, 120, 120, 25, "Hauptdaten A:", #PB_Text_Right)
Text_3 = TextGadget(#PB_Any, 20, 150, 110, 20, "Hauptdaten B:", #PB_Text_Right)
Text_4 = TextGadget(#PB_Any, 20, 180, 110, 20, "Langtexte:", #PB_Text_Right)
Text_5 = TextGadget(#PB_Any, 140, 90, 220, 20, "")
Text_6 = TextGadget(#PB_Any, 140, 120, 200, 20, "")
Text_7 = TextGadget(#PB_Any, 140, 150, 230, 20, "")
Text_8 = TextGadget(#PB_Any, 140, 180, 230, 20, "")
Button_0 = ButtonGadget(#PB_Any, 310, 230, 100, 25, "Abbruch")
WaitWindowEvent() 


While ee<anzahl/3
  a+1
  b+1
  c+1
  ee+1
 
; ++++++++++
  If ElapsedMilliseconds()-verzoegerung=>100; nur alle 100ms aktuallisieren
    verzoegerung=ElapsedMilliseconds()
; ++++++++++

    ;Gadgets aktualisieren
    SetGadgetText(Text_0,Str(a+b+c)+" von "+Str(anzahl))
    SetGadgetState(ProgressBar_0,a+b+c)
    SetGadgetText(Text_6,Str(a)+" von "+Str(anzahl/3))
    SetGadgetText(Text_8,Str(b)+" von "+Str(anzahl/3))
    SetGadgetText(Text_7,Str(c)+" von "+Str(anzahl/3))
    
    Repeat
      WindowEvent=WindowEvent()
      Select WindowEvent
        Case #PB_Event_Gadget
          ;Abbruch Button abfragen
          If EventGadget()=Button_0
            result=MessageRequester("Achtung!","Möchten Sie wirklich abbrechen?",#PB_MessageRequester_YesNo)
            If result=#PB_MessageRequester_Yes          
              End      
            EndIf
          EndIf
      EndSelect
    Until WindowEvent=0
    
  EndIf
    
Wend
mfg kevin
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Re: SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von Micha122 »

Zunächs Danke an alle für die zahlreichen Antworten! :allright:

@ STARGÅTE
Also, das Auge kann gerade mal ~24 Einzelbilder pro Sekunde wahrnehmen, es ist also quatsch hier innerhalb weinger Sekunden 10000 änderungen an einem Gadget durchknallen zu lassen.
Muss Dir Recht geben, tausende Aktualisierungen die Sekunde sind wirklich verschwendete CPU- Zeit.
Werde das ganze mal mit Timern ausprobieren und WaitWindowEvent ersetzen.

@alle
Das zweite WaitWindowEvent hatte ich eingefügt, weil die Gadgets nicht aktualisiert wurden (zumindest unter Linux).

@Kiffi
Dein Code sieht interessant aus, muss aber erst mal noch ein bisschen PB lernen um da alles zu verstehen.
Hab am Anfang nicht erwähnt das mein Code eine dll ist, ich glaube da klappt das so ohnehin nicht.

Grüße, Michael
Barcodes for PureBasic - http://micha122.bplaced.net/
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: SetGadgetText und SetGadgetState sehr CPU lastig?

Beitrag von ts-soft »

Micha122 hat geschrieben:Werde das ganze mal mit Timern ausprobieren und WaitWindowEvent ersetzen.
Aber nicht mit WindowEvent() sondern mit WaitWindowEvent(50), wobei 50 nur exemplarisch genommen wurde.
WindowEvent() ist hier eher nicht geeignet und bei Deinem Verständnis für Fenster und EventLoop wird das
ansonsten weiterhin in einem CPU-Braten ausarten :wink:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten