Denkanstoß wegen Timer Verwendung - kleines aber nerviges Problem.

  • VB.NET
  • .NET (FX) 4.0

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Cheffboss.

    Denkanstoß wegen Timer Verwendung - kleines aber nerviges Problem.

    Moin! :)
    Ich brauche einen Denkanstoß, um ein kleines Problem zu lösen.
    Ich habe zwei Forms erstellt und wenn die Zeit abgelaufen ist, soll eine zweite Form aufgerufen werden.
    Deshalb habe ich den Timer1 beim öffnen der zweiten Form auf „Enabled = False“ gestellt.
    Nach dem beenden dieser Form wird er wieder „Enabled = True“ gestellt.

    Die Überprüfung soll nur dann stattfinden, wenn das Programm im System Tray ist.
    Bei Doppelklick auf das ICON im System Tray, wir das Programm wieder sichtbar!
    Aber jetzt sollte der Timer1 auf “ Enabled = False“ gestellt sein.

    Wenn man aber das Programm aus dem System Tray holt und bereits ein anderes Fenster angezeigt wird und man dieses Fenster dann schließt.
    Wird der Timer1 wieder „Enabled = True“.
    Das soll er aber, in diesem Fall nicht tun!

    Ich hoffe ich könnte das Problem gut Beschreiben!
    Und freue mich auf eure Hilfe.

    BIG THX




    edit1:
    Ich habe den Quellcode der WinForms gelöscht!
    Unten ist nun das ganze Projekt zum herunterladen!
    Außerdem meine weitere Antwort an euch. :!:
    Visual Basic.NET 8o
    MS-SQL
    8o

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Cheffboss“ ()

    @Cheffboss Warum packst Du nicht den kompletten Code in die ZIP, dass wir das Projekt nur noch öffnedn müssen :?:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    In deinem Bild steht Enabled = False, du sagst dein Problem ist, dass ein Timer fälschlicherweise aktiviert wird, dementsprechend müssen wir doch an einem Enabled = True schrauben.
    Da muss also nur die richtige Bedingung davor stehen, weiter hab ichs aber noch nicht verstanden, dass ich wüsste, was die richtige Bedingung wäre.

    Erstmal gehts damit los, was sind das für Fenster?
    Ein Haupt- und eine Nebenform oder zweimal dasselbe Form?
    Welches Form wird über den SystemTray aufgerufen, welches über den Timer?

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Bitte nochmal für Leute mit weniger Nervenzellen und Hirnkapazität wie mich.
    Hab ich das richtig verstanden?
    1. Wenn App in SysTray ist, wird ein Timer gestartet.
    2. Wenn der Timer piept, kommt Form2 (wohl irgend ne Meldung) ins Spiel und der Timer wird deaktiviert.
    3. Wenn Form2 geschlossen wird, wird der Timer reaktiviert.
    4. Wenn aber das SysTrayIcon angeklickt wird und Form2 noch da ist, soll Punkt 2 und 3 gelten (Timer deaktiviert, Reaktivierung erst nach Form2-Schließung).

    Falls das stimmt, was soll passieren, wenn das SysTrayIcon angeklickt wird, aber Form2 NICHT existiert? Betrifft die abgeänderte Situation in Punkt 4.
    Wie kann die App nur im SysTray sein, wenn Form2 angezeigt wird? Betrifft auch Punkt 4.
    Was passiert mit dem Timer, wenn die App normal angezeigt wird, also nicht im SysTray ist?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @RodFromGermany
    Ich habe das Projekt nun als Ganzes hochgeladen.
    In Zukunft werde ich das nun immer so machen.
    Dachte das wäre besser….

    @Haudruferzappeltnoch
    Es ist das Hauptfenster, dass minimiert werden soll.
    In diesen ist ein Timer1 eingefügt, dieser prüft in einem Zeitintervall und Öffnet dann ein neues Fenster(frmOpenFenster).
    Wenn man das Hauptfenster wieder aufruft, soll der Timer1 auf „Enabled = False“ eingestellt werden.

    Wenn man aber das Hauptfenster öffnet, wenn noch das andere Fenster geöffnet ist, wird der Timer1 wieder aktiv!
    (Zeile 22 - frmHaupt.vb)
    Genau dort, liegt der Fehler!
    Ich möchte, wenn bereits ein anderes Fenster angezeigt wird und dann das Hauptfenster wiedererscheint!
    Das der Timer1 aus bleibt!

    @VaporiZed
    1. Ja
    2. Ja
    3. Ja, der Timer1 wird dann wieder aktiv!
    4. Ja, wenn man auf das System Tray-Icon klickt soll der Timer1 aus gehen. Aber beim Beenden von Form2 wird dieser nochmals gestartet! (Dort muss man etwas ändern…)

    @ErfinderDesRades
    Ich habe nun versucht das Problem besser zu erklären.
    Ich hoffe man kann das jetzt besser verstehen!
    Das Projekt ist auch hochgeladen!

    @An alle
    BIG THX :thumbup: , für eure Hilfe.

    Projekt:
    Fehlercode gelöscht!
    Projekt (Siehe unten)
    Visual Basic.NET 8o
    MS-SQL
    8o

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Cheffboss“ ()

    Folgende Fragen wurden nicht beantwortet.

    VaporiZed schrieb:

    Falls das stimmt, was soll passieren, wenn das SysTrayIcon angeklickt wird, aber Form2 NICHT existiert? Betrifft die abgeänderte Situation in Punkt 4.
    Wie kann die App nur im SysTray sein, wenn Form2 angezeigt wird? Betrifft auch Punkt 4.
    Was passiert mit dem Timer, wenn die App normal angezeigt wird, also nicht im SysTray ist?

    Warum ist das SysTrayIcon eigentlich überhaupt noch da, wenn frmOpenFenster angezeigt wird?
    Mach doch eine zusätzliche Variable rein:

    VB.NET-Quellcode

    1. Private KeepTimerStopped As Boolean = False
    2. '…
    3. Private Sub NotifyIcon1_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles NotifyIcon1.MouseDoubleClick
    4. Me.Timer1.Stop() ' <----------
    5. KeepTimerStopped = True
    6. Me.NotifyIcon1.Visible = False
    7. Me.Show()
    8. End Sub
    9. '…
    10. Me.Timer1.Stop() ' <----------
    11. Dim neues_formular As New frmOpenFenster(AlleWerte(0), AlleWerte(1))
    12. neues_formular.ShowDialog(Me)
    13. If Not KeepTimerStopped Then Me.Timer1.Start() ' <----------
    14. KeepTimerStopped = True


    Vielleicht reicht das schon. Aber besser wäre, wenn Du genau erklärst, was wann passieren soll und was wann nicht. Also alle möglichen Situationen beschreiben.

    ##########

    Eigentlich wäre hier sogar ein guter Grund mit IOSP zu arbeiten. In dem EventHandler listest Du nur die Methoden auf, die Dir über den Namen sagen, was passieren soll und in den Methoden selbst sagst Du, wie das passieren soll, was der Methodenname besagt. So kannst Du schnell erkennen, ob es vollständig und in der richtigen Reihenfolge passiert.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Hm, also richtigerweise müsstest du in frm2 im Closed Event ein selfmade Event des HauptFormss raisen. Und in dem Event sagst du Timer1.Start, statt in deiner Zeile 22 im Timer.Tick Event.

    Unschön kannst du dasselbe erreichen, indem du im Closed Event von frm2 einfach direkt Hauptfrm.Timer.Start aufrufst. Aber das kann auch schnell Murks geben.

    Alternativ kannst du schlicht verhindern, dass das Hauptform aufgerufen werden kann, wenn frm2 aktiv ist. Zum Beispiel

    VB.NET-Quellcode

    1. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    2. ...
    3. Me.Timer1.Stop() ' <----------
    4. NotifyIcon1.Visible = False 'Oder stattdessen: RemoveHandler NotifyIcon1.MouseDoubleClick, AddressOf NotifyIcon1_MouseDoubleClick
    5. Dim neues_formular As New frmOpenFenster(AlleWerte(0), AlleWerte(1))
    6. neues_formular.ShowDialog(Me)
    7. NotifyIcon1.Visible = True 'Oder stattdessen: AddHandler NotifyIcon1.MouseDoubleClick, AddressOf NotifyIcon1_MouseDoubleClick
    8. Me.Timer1.Start() ' <----------
    9. ...
    10. End Sub
    Das würd ich zuerst probieren (geht auch in Richtung Vapos Frage bezüglich der Anwählbarkeit des Systrays wenn der Dialog aktiv ist), die Alternative im Kommentar zeigt es dennoch an, aber das Klicken geht halt trotzdem nich.
    Danach Vorschlag 1

    Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    @an alle
    BIG THX. :thumbup:
    Ich habe das Problem nun gelöst.
    Danke, für eure Unterstützung.

    Ich habe das Projekt hochgeladen, für alle die auch mal so ein ähnliches Problem haben!

    Hier der Code:
    Im Timer1:

    VB.NET-Quellcode

    1. ' Prüfe ob noch Einträge vorhanden sind...
    2. If Me.ListBox1.Items.Count > 0 Then
    3. Me.ListBox1.Items.RemoveAt(i)
    4. Else
    5. Me.Timer1.Enabled = False
    6. Exit Sub
    7. End If


    Im NoticyIcon1_MouseDobleClick:

    VB.NET-Quellcode

    1. Me.ListBox1.Items.Clear()
    2. Dim thread1 As System.Threading.Thread
    3. thread1 = New Threading.Thread(AddressOf WaitToListbox_IsClear)
    4. thread1.IsBackground = True
    5. thread1.Start()


    in der frmHaupt:

    VB.NET-Quellcode

    1. Private Sub WaitToListbox_IsClear()
    2. Dim stopwatch As New Stopwatch()
    3. stopwatch.Start()
    4. Do
    5. If Me.ListBox1.Items.Count = 0 Then ' Bis Listbox1 leer ist....
    6. Exit Do
    7. ElseIf stopwatch.Elapsed.Seconds = 10 Then ' Oder bis 10 Sekunden vorbei sind...
    8. Exit Do
    9. End If
    10. Threading.Thread.Sleep(100) ' Kurze Pause, um CPU-Last zu verringern...
    11. Loop
    12. stopwatch.Stop()
    13. Me.Timer1.Enabled = False
    14. End Sub


    Projekt:
    TimerBug_fertig.zip

    edit1:
    Ich habe gerade versucht die Sub (WaitToListbox_IsClear()) ohne einen Thread aufzurufen verwendet!
    Und das geht auch!
    Aber meine Frage ist das mit dem Thread besser als ohne?
    Weil ich möchte nicht, das die GUI einfriert...
    Was sagt Ihr dazu? ?(
    Visual Basic.NET 8o
    MS-SQL
    8o

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Cheffboss“ ()

    VB.NET-Quellcode

    1. Private Async Sub NotifyIcon1_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles NotifyIcon1.MouseDoubleClick
    2. Await Task.Run(Sub() ListBox1.Items.Clear)
    3. End Sub
    Schau auch hier

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Cheffboss schrieb:

    Aber meine Frage ist das mit dem Thread besser als ohne?
    Weil ich möchte nicht, das die GUI einfriert...
    Nebenläufigkeit ist immer eine aufwändige und riskante Krücke.
    Und lausig zu debuggen.
    Wenn du ein Problem ohne das lösen kannst, ist immer besser.

    Async/Await erleichtert ein bischen die Handhabung, aber nur ein bischen, und nur im Vergleich zu vorher.
    Nebenläufigkeit wird nie einfach werden, weil die Probleme liegen in der Natur der Sache:
    Nämlich es ist unbestimmt, wo im Ablauf das Programm sich grade befindet, weil es befindet sich an zwei Stellen gleichzeitig :S

    Friert denn dein GUI ein? Wenn nicht - lass die Finger davon.



    @Haudruferzappeltnoch: Dein Code bringt nix ListBoxItems.Clear ist nicht awaitable.