Seite 1 von 2

Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 09.08.2013 15:57
von SBond
Hi Leute,

habe mal wieder eine Frage an euch. Ich arbeite gerade an einem Software-Oszilloskop (hier ein paar Bilder: http://forum.arduino.cc/index.php?topic=160703.60).
Die Daten die ich auswerte, erhalte ich über die COM-Schnittstelle. An sich funktioniert alles gut. ...doch sobald ich mit der Maus die Titelleiste anklicke und den Maus-Button gedrückt halte, pausiert das Programm. Es führt nach wenigen Millisekunden zum Pufferüberlauf und die Daten sind somit inkonsistent.

Nach langem hin und her habe ich es nun über einen zweiten Thread gelöst, das soweit auch funktioniert. Das Problem ist aber immer wieder die Übergabe oder das Verwenden von Resourcen/Variablen, wenn mehrere Threads auf eine Resource zeitgleich zugreifen wollen. Ich kann das Problem zwar lösen, aber es ist irgendwie nicht das gelbe vom Ei. Schöner wäre es, wenn ich auf diese Threads verzichten könnte. Das würde viele Probleme im Keim ersticken.

Ist es möglich, dass das Programm immer läuft und niemals pausiert? Gibt es da irgendwo eine Einstellung oder ähnliches?

lg
SBond

Re: Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 09.08.2013 17:05
von NicTheQuick
Wenn deine Ereignisschleife stehen bleibt, sobald du das Fenster verschiebst, kannst du das ändern, indem du den Timeout-Parameter von 'WaitWindowEvent()' verwendest oder einen Window-Timer mit 'AddWindowTimer()' benutzt. Beispiele dazu findest du in der Hilfe.

An deiner Stelle würde ich aber trotzdem die Thread-Variante bevorzugen. Allerdings musst du dann auch wissen wie du die Daten zwischen Thread und Hauptprogramm sauber austauschst. Dazu gibt es Mutex und Semaphoren. Bei den Semaphoren gibt es in der Hilfe ein schönes Beispiel zum Austausch von Daten zwischen Thread und Hauptprogramm.

Re: Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 09.08.2013 17:17
von SBond
das mit den Parametern scheint aber nicht so recht zu klappen :(
Ich nutze WaitWindowEvent() mit 2ms TimeOut, aber das Pausieren lässt sich trotzdem nicht verhindern.

Hast du eventuell ein Code-Beispiel? Eventuell bin ich ja auch einfach nur zu blöd um es richtig anzuwenden.


Wahrscheinlich ist es wirklich besser mit Threads zu arbeiten.

lg
SBond

Re: Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 09.08.2013 20:06
von HeX0R
SBond hat geschrieben:das mit den Parametern scheint aber nicht so recht zu klappen :(
Ich nutze WaitWindowEvent() mit 2ms TimeOut, aber das Pausieren lässt sich trotzdem nicht verhindern.
Das lässt sich in der Tat nur durch Threads verhindern.
Ich habe dieses Verhalten schon vor ewigen Zeiten offiziell bemängelt, es interessiert aber keinen.
Schlimm ist ja nicht nur, dass die Ereignisschleife einfriert, viel schlimmer ist, dass dabei Events verloren gehen.

Wenn man nun z.B. von Threads über Window-Events mit seiner Hauptschleife kommunizieren will, kann es passieren, dass ein Dir wichtiges Signal nicht ankommt, weil der Anwender die Frechheit besessen hat, das Fenster währenddessen herumzuschieben...

Re: Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 09.08.2013 20:19
von ts-soft
Zumindest mit BindEvent() genutzte Events kommen auch beim verschieben an. So kann man sich dann doch
noch etwas behelfen.

Re: Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 09.08.2013 21:27
von Lambda
Was du auf Windows benötigen würdest wäre #WM_MOVE.

Code: Alles auswählen


Procedure WinProc(hWnd, Msg, wParam, lParam)
  Protected Old = GetProp_(hWnd, "PROC")
  Static Count
  
  Select Msg
    Case #WM_MOVE
      Count + 1
      Debug "Move"+Str(Count)
  EndSelect
  
  ProcedureReturn CallWindowProc_(Old, hWnd, Msg, wParam, lParam)
EndProcedure

OpenWindow(0, 0, 0, 400, 300, "Move", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
SetProp_(WindowID(0), "PROC", SetWindowLongPtr_(WindowID(0), #GWL_WNDPROC, @WinProc()))

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver

Re: Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 09.08.2013 23:58
von HeX0R
ts-soft hat geschrieben:Zumindest mit BindEvent() genutzte Events kommen auch beim verschieben an. So kann man sich dann doch
noch etwas behelfen.
Ach, ist das tatsächlich so?
Ich habe das nie ausprobiert, weil ich dachte "geht bestimmt eh nicht".

Re: Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 10.08.2013 00:12
von ts-soft
HeX0R hat geschrieben:Ach, ist das tatsächlich so?
Ich habe das nie ausprobiert, weil ich dachte "geht bestimmt eh nicht".

Code: Alles auswählen

EnableExplicit

Procedure SetTime()
  SetWindowTitle(0, FormatDate("%hh:%ii:%ss", Date()))
EndProcedure

OpenWindow(0, #PB_Ignore, #PB_Ignore, 640, 480, "")
AddWindowTimer(0, 1, 500)
BindEvent(#PB_Event_Timer, @SetTime())

While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend 
Uhr läuft auch beim verschieben des Fensters weiter :wink:

Re: Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 10.08.2013 13:27
von SBond
ist natürlich interessant. So wie ich das sehe, ist die Funktion aber erst in der PB 5.20 enthalten. Ich warte aber erst noch etwas, bis die Version aus der Beta-Phase ist.

Ich denke mal, dass ich wohl bei den Threads bleiben muss. Ich habe da aber immernoch Probleme ein Array aus einem Thread in die Main-Schleife zu übertragen, ohne dass es zu Zugriffskonflikten kommt. Ich denke mal das Zauberwort wird Mutex sein.

Re: Problem: Programm pausiert beim Verschieben des Fensters

Verfasst: 10.08.2013 13:44
von Bisonte
Da das neue BindEvent() und seine Brüder eigentlich aus dem Callback des Windows direkt abgreifen, kannst du dir mit
einem eigenen WindowCallback behelfen.

Das Timer Beispiel von TS-Soft als Callback :

Code: Alles auswählen

EnableExplicit

#MeinTimer = 123 ; sollten ab 121 beginnen, um Konflikte zu vermeiden

Procedure WindowCallBack(hWnd, uMsg, wParam, lParam)
  
  Protected Result = #PB_ProcessPureBasicEvents
  
  Select uMsg

    Case #WM_TIMER ; <-- Das Fenster erhält ein Timer Event
      ; ---  Hier wird der Timer abgefragt
      ; --- in wParam steht die TimerEvent Nummer
      If wParam = #MeinTimer
        SetWindowTitle(0, FormatDate("%hh:%ii:%ss", Date()))
      EndIf
      
      ; --- Sollte man den Timer nicht mehr brauchen
      ; KillTimer_(hWnd, #MeinTimer)
      
  EndSelect

  ProcedureReturn Result
  
EndProcedure


OpenWindow(0, #PB_Ignore, #PB_Ignore, 640, 480, "")

; --- Ersatz für
; AddWindowTimer(0, #MeinTimer, 500)
SetTimer_(WindowID(0), #MeinTimer, 500, #Null) 

; --- Ersatz für
; BindEvent(#PB_Event_Timer, @SetTime())
SetWindowCallback(@WindowCallBack(), 0)
; --- Und die Auswertung erfolgt im Callback

While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend 
Wenn man einige merkwürdige Logiken von MS geschnallt hat, ist WindowAPI gar nicht mehr so
rätselhaft ... ;)