Invoke Toolstripbutton aus Timer

  • VB.NET
  • .NET 4.5

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von Westerwälder.

    Invoke Toolstripbutton aus Timer

    Hallo,

    versuche einen Toolstripbutton sichtbar zumachen.

    Habe zwei Lösungsansätze, welche aber nicht funktionieren.

    VB.NET-Quellcode

    1. Public Shared Sub SetVisibleToolStripButton(ByVal toolStripName As ToolStrip, ByVal buttonName As ToolStripButton, ByVal Sichtbar As Boolean)
    2. If toolStripName.InvokeRequired Then
    3. toolStripName.Invoke(CType((Sub()
    4. buttonName.Visible = Sichtbar
    5. End Sub), System.Action))
    6. Else
    7. buttonName.Visible = Sichtbar
    8. End If
    9. End Sub
    10. Public Sub Sichtbar_Fremddaten(ByVal Anzeigen As Boolean)
    11. 'Wird aus Timer Elapsed aufgerufen.
    12. '1. Variante
    13. SetVisibleToolStripButton(ToolStrip_Menue, TS_Fremddaten, Anzeigen)
    14. Exit Sub
    15. '2. Variante
    16. Me.Invoke(Sub() TS_Fremddaten.Visible = Anzeigen)
    17. End Sub

    Gruß Markus
    Solange davon nix nebenläufig passiert, brauchst Du gar kein Invoke. Kommt natürlich drauf an, was bei Dir ein Timer ist. Die Timer-Komponente aus der Toolbox läuft im GUI-Thread.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Wozu also Invoke?
    Ruft der EventHandler auch eine der Subs auf? Steht nirgends. Wenn ja, was kommt an? Stichwort Ablaufverfolgung
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Es wird eine Sub in einer Class aufgerufen, nicht in der Form des Toolstrip.

    VB.NET-Quellcode

    1. Public Sub StatusPruefen()
    2. Datenupdate = False
    3. DateiInfo = New FileInfo(DateiZugriff_Daten)
    4. NeueLesung_Daten = DateiInfo.LastWriteTime
    5. If Not NeueLesung_Daten = LetzteLesung_Daten Then
    6. Datenupdate = True
    7. Startmenue.Sichtbar_Fremddaten(True) '#######################################
    8. Startmenue.Datenausgabe_NotifySystemmeldung("Drittdaten wurden aktualisiert.")
    9. Journal.Ereignis.Schreiben("Drittdaten wurden aktualisiert.")
    10. Kontroll.Info.Info_Setzen(Now, "Drittdaten aktualisiert")
    11. LetzteLesung_Daten = NeueLesung_Daten
    12. End If
    13. End Sub


    Sehe gerade kann ja den Datenupdate public machen und dies in einem Tick-Timer auswerten.
    Gruß Markus

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Westerwälder“ ()

    Westerwälder schrieb:

    Public WithEvents Timer_FuenfSek As New Timer With {.Enabled = False, .Interval = 5000}
    So lange der Timer auf .Enabled = False steht, tickt er nicht. ;)
    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!
    Danke Rod, aber gut das es eine Sub New für Klassen gibt.

    VB.NET-Quellcode

    1. Public Sub New()
    2. Info = New CInfo
    3. Pruefung = New CPruefung
    4. Aktion = New CAktion
    5. Weckzeiten = New CWecker
    6. AnalyseListe = New List(Of String)
    7. Internet_Erledigt = False
    8. Starthintergrund_Erledigt = False
    9. InternetVerbunden = True
    10. MB.Rechner.InEnergiesparmodus = False
    11. MB.Rechner.WirdRuntergefahren = False
    12. Timer_FuenfSek.Enabled = True
    13. End Sub
    Gruß Markus

    Westerwälder schrieb:

    gut das es eine Sub New für Klassen gibt.
    Dann pack die komplette Instanziierung da rein, Deine Aufteilung macht keinen Sinn und ist verwirrend.
    In einem halben JAhr auch für Dich selbst.
    Und:
    Die Sub New heißt Konstruktor.
    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!
    Guten Morgen,

    EDR:
    Es gibt keine Fehlermeldung. Der ToolstripButton wird einfach nicht sichtbar, solange dies aus dem Timer aufgerufen wird.
    Testweise manuell aus der Form direkt, funktioniert es.

    ROD:
    Wieso mache ich das so?
    Benötige für ein Programmlauf nicht immer alle Klassen. Rufe sie bei Bedarf mit New auf.
    So arbeitet, wie in diesem Fall hier, der Timer nur, wenn die Klasse benötigt wird.
    Ist der Gedanke so falsch nun?
    Gruß Markus

    Westerwälder schrieb:

    Ist der Gedanke so falsch nun?
    Missverständnis.
    Pack die Instanziierung des Timers in den Konstruktor, wo DEIN_TIMER.Enabled = True drinne steht.
    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!
    Denke Du meinst das hier: Public WithEvents Timer_FuenfSek As New Timer With {.Enabled = False, .Interval = 5000}
    Interval und Enabled nicht bei der Deklaration, sondern im Konstruktor Sub New zuweisen.
    Public Deklarieren kann ich ja nicht in einer Sub.
    Oder reden wir nun ganz einander vorbei?
    Gruß Markus

    Westerwälder schrieb:

    Es gibt keine Fehlermeldung.
    Das deutet stark darauf hin, dass du im MultiThreading-Szenario mit der DefaultForm-Instanz arbeitest.
    Damit fliegt jeder mal auf Nase.
    Also

    VB.NET-Quellcode

    1. Form1.Invoke(blabla)
    2. Form1.ToolstripBar.Machwas()
    3. '...
    sowas alles geht aus Nebenläufigkeit heraus einfach nicht, weil der Thread nicht das Form1 anspricht, was du siehst, sondern er erstellt sich ein neues Form1, was du nicht siehst, und agiert da drauf.

    Westerwälder schrieb:

    Dim NeueForm As Form = Startmenue

    Jo, das ist schonmal ein Zugriff via DefaultProperty.
    Jetzt kann ich überhaupt auch erkennen, dass Startmenue eine Form-Klasse ist (für die so eine vermaledeite DefaultProperty leider existiert). Obiges ist aber wohl noch im MainThread.
    Aber hier findet sich ebenso ein Zugriff über die Startmenue-Default-Property - und ich vermute, das wird von deim Timer aufgerufen (und der tickt nebenläufig):

    Westerwälder schrieb:

    VB.NET-Quellcode

    1. Public Sub StatusPruefen()
    2. '[...]
    3. Startmenue.Sichtbar_Fremddaten(True) '##### das hier failt!
    4. Startmenue.Datenausgabe_NotifySystemmeldung("Drittdaten wurden aktualisiert.") ' dito
    5. '[...]
    6. End Sub
    Und das ist vmtl. der Quell des Übels.
    Man kann das vergleichsweise einfach fixen, indem du einen System.Windows.Forms.Timer nimmst statt des Timers.Timer, den du glaub hast.
    Weil ich glaub, du brauchst da gar keine Nebenläufigkeit.
    Dies hier funktioniert, weil ich kein Control der Form anspreche.

    VB.NET-Quellcode

    1. Public Sub Datenausgabe_NotifySystemmeldung(ByVal NotiText As String, Optional ByVal NotiTitel As String = "MBHome",
    2. Optional ByVal Anzeigedauer As Integer = 1000)
    3. With Notify_System
    4. .BalloonTipTitle = NotiTitel
    5. .BalloonTipText = NotiText
    6. .Visible = True
    7. .ShowBalloonTip(Anzeigedauer)
    8. Threading.Thread.Sleep(Anzeigedauer + Anzeigedauer)
    9. .Visible = False
    10. End With
    11. End Sub


    Im Grunde sind mir die Timers.Timer lieber, wenn nicht auf Control's zugegriffen werden muss. War nun hier nachträglich eine Änderung.
    Falls der User das Update anhand des Notify nicht mit bekommen hat, sieht er es nun an dem eingebelendeten ToolstripButton im Startmenue.
    Gruß Markus
    @Westerwälder So was:

    VB.NET-Quellcode

    1. Public WithEvents Timer_FuenfSek As Timer
    2. Public Sub New()
    3. Timer_FuenfSek = New Timer
    4. Timer_FuenfSek.Interval = 5000
    5. Timer_FuenfSek.Enabled = True
    6. End Sub
    oder mit With {.Enabled = False, .Interval = 5000}
    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!