NotifyPropertyChanged und DispatcherTimer

  • WPF

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von seh.

    NotifyPropertyChanged und DispatcherTimer

    Hallo,

    ich hab ein kleines Problemchen und zwar updated ein Label dessen Text Wert ein Binding auf einen String in meinem ViewModel nicht in dem Tick Event vom Dispatcher Timer. Kann es sein dass das nicht klappt weil das Tick Event nicht im UI Thread läuft?

    Der Timer wird im Konstruktor des Viewmodels erstellt, das Tick Event abonniert und ein 5 Sekunden Intervall festgelegt und anschließend gestartet.
    Im Konstruktor calle ich dann auch einmal manuell das Tick Event damit es von Anfang an ausgeführt wird.
    In dem Tick Event wird einfach nur die String Variable gesetzt.

    C#-Quellcode

    1. var ​updateTimer = new DispatcherTimer();
    2. updateTimer.Interval = new TimeSpan(0, 0, 5);
    3. updateTimer.Tick += UpdateTimer_Tick;
    4. updateTimer.Start();
    5. UpdateTimer_Tick(this, EventArgs.Empty);


    Meine Property sieht so aus:

    C#-Quellcode

    1. ​private int firewallLevel { get; set; }
    2. public int FirewallLevel
    3. {
    4. get
    5. {
    6. return firewallLevel;
    7. }
    8. set
    9. {
    10. firewallLevel = value;
    11. NotifyPropertyChanged();
    12. }
    13. }


    Am Anfang der Call zur Tick funktioniert auch, das Label wird initial gesetzt, doch alle weiteren Ticks die durch den Timer verursacht werden, klappen net. Wie kann ich das ganze mit dem Timer funktional machen?
    Ich habe auch schon im Tick Event probiert mit:

    C#-Quellcode

    1. ​Application.Current.Dispatcher.Invoke()
    die Property zu setzen, aber das ging auch nicht.

    Irgendwelche Ideen?

    Grüße
    Hallo @seh

    Zeig mal am besten was du in der UpdateTimer_Tick drinnen hast.
    Selbst wenn es daran liegt das du aus dem UI Thread heraus ein Property änderst (was ich auch glaube) MUSST du eine Exception um die Ohren geworfen bekommen.

    Und wie hast du Disptcher Invoke eingesetzt?
    Application.Current.Dispatcher.Invoke(Sub() myProperty = "Test")

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hi, @Nofear23m

    meine UpdateTimer_Tick sieht so aus:

    C#-Quellcode

    1. private void UpdateTimer_Tick(object sender, EventArgs e)
    2. {
    3. Update();
    4. UpdateStore();
    5. UpdateTasks();
    6. UpdateMiner();
    7. CheckDesiredUpdates();
    8. }


    Wichtig dabei ist jetzt erstmal nur der erste call zur UpdateStore();
    Diese sieht so aus:

    C#-Quellcode

    1. private void UpdateStore()
    2. {
    3. Task.Run(async () =>
    4. {
    5. var request = new vhUtils.vhRequest();
    6. request.InitReq("store.php");
    7. JsonConvert.PopulateObject(await request.ExecuteAsync(), AppStoreSingleton.Instance);
    8. });
    9. FirewallLevel = AppStoreSingleton.Instance.Apps.Find(a => a.AppId == EAppId.Firewall).Level;
    10. }


    Das ​await request.ExecuteAsync() führt eine WebRequest zu ner API aus.
    Mir ist durchaus bewusst, dass das Ergebnis nicht umbedingt schon da ist wenn ich dann die FirewallLevel Property setze, da das Request u.U. natürlich länger dauert, aber beim nächsten Mal wenn der Timer zuschlägt wird der Wert dann gesetzt sein... Ist zwar bisher unsauber, aber wenn ich das FirewallLevel Setzen in das async mit rein nehme, läufts ja auch nicht aufm UI Thread und dann funktioniert es ja auch ned.

    Das mit dem Application.Current.Dispatcher.Invoke hab ich so probiert (einfach um das Setzen der FirewallLevel wie oben drum):

    C#-Quellcode

    1. private void UpdateStore()
    2. {
    3. Task.Run(async () =>
    4. {
    5. var request = new vhUtils.vhRequest();
    6. request.InitReq("store.php");
    7. JsonConvert.PopulateObject(await request.ExecuteAsync(), AppStoreSingleton.Instance);
    8. });
    9. Application.Current.Dispatcher.Invoke(() => {
    10. FirewallLevel = AppStoreSingleton.Instance.Apps.Find(a => a.AppId == EAppId.Firewall).Level;
    11. });
    12. }
    Mal langsam mit den Pferden.

    Deine Asyncrone Abfrage bringt doch gar nix?!?!
    Solange deine Void nicht Awaitable gekennzeichnet ist wird auch nicht gewartet.
    eines wissens trotz Tasl.Run.

    Mal abgesehen davon das es auch keinen Sinn hat. Wir haben ja heue gelernt das in ein Timer ja anscheinend sowieso in einem Nebentread läuft oder?
    Zumindest mit dem Aufruf von dir.

    Anders enn du es machst wie folgt. So sollte übrigens auch aktualisiert werden.
    Dispatcher.Invoke(Sub() UpdateStore)

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Jep!!!

    Grüße
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ach Mann, er hat die ganze Zeit updated... Ist ein dummer Fehler gewesen von mir den ich sicher nie wieder machen werde.

    Und zwar JsonConvert.PopulateObject füllt zwar eine Liste aus, wenn diese aber schonmal befüllt wurde wird diese weiter befüllt und nicht gecleared. Wenn ich jetzt mit Find nach einem Wert suche, finde ich immer den selben ersten obwohl das ganze Datenset nochmal vorhanden war aber schon mit aktuelleren Werten. Boahhhh Mist! :D

    Danke für deine Hilfe @Nofear23m