Seite 2 von 3

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 14.06.2018 19:25
von Thomas
Danke euch Beiden für eure Tipps! :)

Gleichzeitig schreiben versteht sich -> Problem
Dürfen zwei Threads gleichzeitig lesen, oder ist der Zugriff generell schon ein Problem?

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 14.06.2018 22:07
von mk-soft
Lesen ist kein Problem...

Ausser bei Listen und Maps

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 14.06.2018 23:00
von Thomas
Noch ein anderer Gedankengang ... Es gibt doch noch diese Timer ...

zum Veranschaulichen von Deeem2031 ausm Forum kopiert:

Code: Alles auswählen

Global quit.l

Procedure xyz(hwnd.l,nIDEvent.l, uElapse.l, lpTimerFunc.l)
  If MessageRequester("","5 Sekunden sind vergangen!"+Chr(10)+"Beenden?",#PB_MessageRequester_YesNo) = 6
    quit = 1
  EndIf
EndProcedure

OpenWindow(0,0,0,0,0,#PB_Window_Invisible,"")
settimer_(WindowID(),1,5000,@xyz()) ; alle 5000 millisekunden (5 sek.) xyz() ausführen

Repeat
  WaitWindowEvent()
Until quit
Muss ich die auch als Threads betrachten (sieht zumindest genauso aus ....)?
Oder sind die stressfrei in der Verwendung?

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 14.06.2018 23:13
von ts-soft
Entweder der Code ist Uralt oder Du hast dort mehrere Syntax-Fehler :mrgreen:

Code: Alles auswählen

Procedure xyz(hwnd.i, nIDEvent.l, uElapse.l, lpTimerFunc.i
Außerdem ist ein MessageReguester Modal (blockierend), ob der so sinnvoll ist. Wenn da keiner auf ja oder nein klickt, nützt der Timer nicht viel.

PS: Ist natürlich kein Thread und ein Thread hat grundsätzlich nur einen Parameter, nicht mehr und nicht weniger!

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 14.06.2018 23:20
von Thomas
öm, ja der Code ist Uralt :D sry

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 15.06.2018 08:54
von RSBasic
Außerdem, wenn du einen Timer benutzen möchtest,brauchst du kein SetTimer_() mehr. PB bietet schon lange eine eigene Funktion an: AddWindowTimer()

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 15.06.2018 10:19
von Thomas
RSBasic hat geschrieben:Außerdem, wenn du einen Timer benutzen möchtest,brauchst du kein SetTimer_() mehr. PB bietet schon lange eine eigene Funktion an: AddWindowTimer()
Jetzt weis ich auch warum ich keine neuen Beiträge mehr zu settimer_ finde, sry, 6 Jahre lügen nicht.

Also, Zwischenstand, zwei Threads hab ich erfolgreich gegen settimer_ ersetzt (werd ich ncoh abändern auf AddWindowTimer()

Der Letzte Thread funktioniert, aber ich denke da ist noch "Crash-Potential" da, das möchte ich noch beheben:

Dieser Code wird vom Timer alle 100ms aufgerufen und erstellt immer wenn sich der Fenstertitel ändert, einen Thread (weiter unten), der aber bevor dieser ein zweites Mal gestartet wird vorher getötet wird.

Code: Alles auswählen

Procedure GetNewWindowTitle()
  
  Static title.s{1024}
  Static Thread_LEDEffects
  Static count.l
 
    If IsWindow_(Window_hWnd)
      GetWindowText_(Window_hWnd, @title, 1024)
      
      If Not Window_Title$ = title
        Window_Title$ = title
        
        If IsThread(Thread_LEDEffects)
          KillThread(Thread_LEDEffects)
        EndIf
        Thread_LEDEffects = CreateThread(@LEDEffects(), 0)
        
        ;Debug "[Title] = " + title
      EndIf
      
    Else
      ;Debug "Programm scheinbar geschlossen"

      If count < 1
        EnumWindows_(@GetWindowHandle(),#True)
        count = 10
      Else
        count = count - 1
      EndIf
  
    EndIf
EndProcedure
Thread:

Code: Alles auswählen

Procedure LEDEffects(Parameter)
  
  Protected path$ = "", trigger$ = "", n, m, o
  
  path$ = Mid(Window_Title$, 29)
  trigger$ = StringField(path$, CountString(path$, "\"), "\") + "\" + GetFilePart(path$)
  
      MyDebug("~ " + Chr(34) + "Screen: " + trigger$ + Chr(34))
  
  For n = 0 To (#LED_CODES_MAX - 1)
    If  CSV_Array(n)\Screen = trigger$
      Repeat 
        For o = 1 To CSV_Array(n)\Sequences
        
          For m = 1 To #LED_MAX
            LED_Array(m - 1, #AM) = Red(CSV_Array(n + o - 1)\LED[m - 1])
            LED_Array(m - 1, #KW) = Green(CSV_Array(n + o - 1)\LED[m - 1])
            LED_Array(m - 1, #WW) = Blue(CSV_Array(n + o - 1)\LED[m - 1])
          Next m
          SendTMP2Data()
          Delay(CSV_Array(n)\Time)
        Next o
      Until CSV_Array(n)\Loop <> 1
      
      
      Break
    EndIf
  Next n
Wo ich gerade noch Verbesserungspotential sehe:
- LED_Array ist Global und übergibt quasi die Daten vom LEDEffects() zu SendTMP2Data()
=> nix global, direkt an die Procedure übergeben. (Wird SendTMP2Data() auch getötet wenn der LEDEffects()-Thread gekillt wird?
- die Window_Title$ wäre denke ich noch gut auch dem Thread anders zu übergeben, da könnte was passiern ...
- Gut die CSV_Array wird am Anfang des Programms gefüttert und dann nur noch vom Thread angefasst, das sollte passen.

Was denkt ihr (soweit man das an den beiden Code-Ausschnitten sehn kann

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 15.06.2018 10:38
von mk-soft
Solltest die mal gedanken machen wegen KillThread.

KillThread ist immer nur der letzte Ausweg und kann zu Speicherlecks führen oder das eine Datei nicht richtig geschrieben wird.

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 16.06.2018 00:10
von Thomas
Macht Sinn.

Wie würdet Ihr das umsetzen ...

Der Fenstertitel wird alle 100 ms abgefragt und in ne Globale Variable geschrieben (AddWindowTimer).
Ändert sich der Fenstertitel, wird ein Thread aufgerufen, der irgendwelche Daten rausschickt, die in nem Array liegen.
Der Thread läuft dann vor sich hin. Muss aber Beendet werden, bevor er wieder aufgerufen wird.

Entweder ich lasse den Thread generell laufen und trigger diesen irgendwie mit dem Fenstertitel.
Aber spätestens wenn ein Delay aufgerufen wird (die Daten werden in nicht regelmäßigen Abständen geschickt), am einfachsten war eben ein Delay zu setzen und dann, nja KillThread hat die Sache dann schon irgendwie beendet.

Was ist das erste was euch dazu einfällt? :praise:

Re: Programm hängt sich unter Windows 10 auf

Verfasst: 16.06.2018 00:56
von ts-soft
Keine globale Variable. Ist bäh!

Mal ganz grob erklärt:

Eine Structure für die Threadvariable erstellen, in der ein Mutex und eine Semaphore und weiteres gespeichert werden. Diese Structurevariable übergibst Du dann an den Thread (als Pointer).

Mit dem Mutex kannste dann das Array absichern und die Semaphore fragst Du vor jedem Schleifendurchlauf ab.

Statt KillThread nutzt Du dann z.B. SignalSemaphore. Sollte die Semaphore dann 1 oder höher sein, beendest Du den Thread.

So in etwa, Programmieren sollst Du das ganze schon selbst :)