none
Slider_ValueChanged() -> Exception RRS feed

  • Frage

  • Wiedermal ein Problem, wo ich anstehe (o;

    In der Funktion Slider_ValueChanged() habe ich zwei Aufrufe:

            private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
            {
                sliderText.Text = e.NewValue.ToString();
                SendSliderValue(e.NewValue);
            }

    Die 2. Funktion macht eine Websocket Verbindung zu meinem Server, der wiederrum Daten testweise an meinen RPi sendet, um so den Wert mit LEDs anzuzeigen.

    Eigenartigerweise bricht das Programm ab mit einer Exception "Object reference not set to an instance of an object", aber nur, wenn ich nach dem Start den Slider von 0 weg bewege.

    Wenn ich hingegen z.B. direkt in die Mitte des Sliders tippe, läuft es normal.

    Die Websocket Funktion habe ich direkt von Microsofts Seite:

    https://code.msdn.microsoft.com/windowsapps/Connecting-with-WebSockets-643b10ab

    Kann es damit zu tun haben, dass die WebSocket Funktion asynchron ist?

    Oder wie behandelt man am besten solche Slider Updates richtig?

    Ach ja...wenn ich das Programm auf dem Windows Phone laufen lasse, zeigt der Framerate Counter 57..sobald der Slider bewegt ist, springt er auf 30 und ist rot markiert.

    Donnerstag, 9. April 2015 16:25

Antworten

  • Mann bin ich gut heute *lol

    Genau das war das Problem. Der WebSocket wird nun beim Initialisieren der Seite geöffnet...Code sieht nun so aus....okay...ein paar mehr Überprüfungen könnten es noch sein...aber keine Exception mehr...und Slider bewegt sich von Anfang an (o;

            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                initWebSocket();
            }
    
            private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
            {
                sliderText.Text = e.NewValue.ToString();
                SendSliderValue(e.NewValue);
            }
    
            private async void initWebSocket()
            {
                // Have we connected yet?
                if (messageWebSocket == null)
                {
                    // Validating the URI is required since it was received from an untrusted source (user input). 
                    // The URI is validated by calling TryGetUri() that will return 'false' for strings that are not
                    // valid WebSocket URIs.
                    // Note that when enabling the text box users may provide URIs to machines on the intrAnet 
                    // or intErnet. In these cases the app requires the "Home or Work Networking" or 
                    // "Internet (Client)" capability respectively.
                    Uri server = new Uri("ws://10.0.100.170:9000/slider", UriKind.Absolute); ;
    
                    messageWebSocket = new MessageWebSocket();
                    messageWebSocket.Control.MessageType = SocketMessageType.Utf8;
                    messageWebSocket.MessageReceived += MessageReceived;
    
                    // Dispatch close event on UI thread. This allows us to avoid synchronizing access to messageWebSocket.
                    messageWebSocket.Closed += async (senderSocket, args) =>
                    {
                        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Closed(senderSocket, args));
                    };
    
                    await messageWebSocket.ConnectAsync(server);
                    messageWriter = new DataWriter(messageWebSocket.OutputStream);
    
                }



    Donnerstag, 9. April 2015 19:31

Alle Antworten

  • Hallo,

    wenn du eine Exception erhältst, sagt dir Visual Studio wo diese aufgetreten ist. Irgend etwas ist null, was einen anderen Wert haben sollte - mehr kann man dazu nicht sagen.

    Asynchrone Methoden handhabt man normalerweise mit async und await. Da dein Eventhandler weder noch enthält, läuft auch nichts asynchron oder zumindest nicht wie ursprünglich gedacht ab.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 9. April 2015 17:08
  • Kleiner Anhang zu den Slidern,

    bei WPF, einer sehr ähnlichen Technologie gab es diesen bug, ich nehme an den gibt des deshalb auch bei Windows Apps:

    Das ValueChanged-Ereignis wird t.T. sehr freü geworfen, sogar bevor alle Steuerelemente geladen worden sind, weshalb man sich da nicht verlassen kann.

    Du solltest deshalb alle Abhängigkeiten gegen null prüfen, also ob alle Elemente überhaupt schon bereit sind. Dann erst forfahren.


    © 2015 Thomas Roskop

    Germany // Deutschland

    Donnerstag, 9. April 2015 17:17
  • Es bricht hier ab:

                UnhandledException += (sender, e) =>
                {
                    if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
                };
    

    Allerdings nur nach dem Aufstarten...danach kann ich den Slider wieder auf 0 setzen und wieder schieben....

    Das ganze sieht so aus (da muss ich wohl ne Lektüre finden für async und so Zeugs ;o)

            private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
            {
                sliderText.Text = e.NewValue.ToString();
                SendSliderValue(e.NewValue);
            }
    
            private async void SendSliderValue(double sliderValue)
            {
                bool connecting = true;
                try
                {
                    // Have we connected yet?
                    if (messageWebSocket == null)
                    {
                        // Validating the URI is required since it was received from an untrusted source (user input). 
                        // The URI is validated by calling TryGetUri() that will return 'false' for strings that are not
                        // valid WebSocket URIs.
                        // Note that when enabling the text box users may provide URIs to machines on the intrAnet 
                        // or intErnet. In these cases the app requires the "Home or Work Networking" or 
                        // "Internet (Client)" capability respectively.
                        Uri server = new Uri("ws://10.0.100.170:9000/slider", UriKind.Absolute); ;
    
                        messageWebSocket = new MessageWebSocket();
                        messageWebSocket.Control.MessageType = SocketMessageType.Utf8;
                        messageWebSocket.MessageReceived += MessageReceived;
    
                        // Dispatch close event on UI thread. This allows us to avoid synchronizing access to messageWebSocket.
                        messageWebSocket.Closed += async (senderSocket, args) =>
                        {
                            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Closed(senderSocket, args));
                        };
    
                        await messageWebSocket.ConnectAsync(server);
                        messageWriter = new DataWriter(messageWebSocket.OutputStream);
    
                    }
    
                    connecting = false;
                    string message = "slider: " + sliderValue.ToString();
    
                    // Buffer any data we want to send.
                    messageWriter.WriteString(message);
    
                    // Send the data as one complete message.
                    await messageWriter.StoreAsync();
    
                }
                catch (Exception ex) // For debugging
                {
                    // Error happened during connect operation.
                    if (connecting && messageWebSocket != null)
                    {
                        messageWebSocket.Dispose();
                        messageWebSocket = null;
                    }
    
                    WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
    
                    switch (status)
                    {
                        case WebErrorStatus.CannotConnect:
                        case WebErrorStatus.NotFound:
                        case WebErrorStatus.RequestTimeout:
                            break;
    
                        case WebErrorStatus.Unknown:
                            throw;
    
                        default:
                            break;
                    }
    
    //                OutputField.Text += ex.Message + "\r\n";
                }
            }
    

    Donnerstag, 9. April 2015 17:21
  • Auf den ersten Blick sehe ich keinen Fehler. Ich empfehle dir daher schrittweise den Code zu debuggen und dabei alle Variablen zu überprüfen. Setze hierfür einen BreakPoint in die erste Zeile des Eventhandlers, indem du F9 drückst. Dann wird der Code an dieser Stelle angehalten und du kannst Zeile für Zeile mit F11 ausführen. Durch F5 kannst du das Programm normal weiter laufen lassen.
    Wenn du auf eine Variable- oder eine Eigenschaft zeigst, kannst du deren Wert erfahren.

    Dort wo dein Code angehalten wurde, ist der globale Exception-Handler der Apps. Dort kannst du ggf. auf den e-Parameter zeigen um nähere Informationen zu erhalten.

    Das von Thomas angesprochene Problem hatten wir erst kürzlich im Forum - ich dachte du hättest die Frage gestellt, dem war aber nicht so. Siehe dir also ggf. auch noch das an: Anfängerfrage: Slider wirft bei aufruf "NullReferenceException", wenn "Value" gesetzt

    Das habe ich an deiner Formulierung nicht zu 100% verstanden, tritt der Fehler schon beim Laden der App- oder erst nach der ersten Interaktion mit dem Benutzer auf? Ist die Value-Eigenschaft des Sliders im XAML gesetzt? 


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 9. April 2015 17:31
  • Ich glaube ich weiss, wo der Fehler liegt....also eher Racecondition...

    Beim ersten Bewegen des Sliders liefert Slider_ValueChanged() einen NewValue von 10 und OldValue von 0.

    Ich habe da Ticks auf 10 eingestellt, Wertebereich von 0 - 100.

    Wenn der Slider dann von 0 bewegt wird, dauert es etwa 1 - 2 Sekunden, bis die Exception kommt...obwohl der Slider den Wert von 10 liefert, steht der Slider etwa auf 3 - 5....

    Beim direktem Klicken ist die Verzögerung etwa gleich, aber ohne Exception, und man kann danach den Slider normal bewegen....

    Der einzige Unterschied ist also....dass noch kein WebSocket geöffnet wurde, und der DNS Lookup, Verbindungsaufbau und WS Handshake zu lange dauert, und damit der Slider nicht aktualisiert wird....

    Also die Lösung muss dann so ausschauen, dass der WebSocket bereits nach dem Initialisieren der Seite geöffnet wird...

    Donnerstag, 9. April 2015 19:11
  • Mann bin ich gut heute *lol

    Genau das war das Problem. Der WebSocket wird nun beim Initialisieren der Seite geöffnet...Code sieht nun so aus....okay...ein paar mehr Überprüfungen könnten es noch sein...aber keine Exception mehr...und Slider bewegt sich von Anfang an (o;

            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                initWebSocket();
            }
    
            private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
            {
                sliderText.Text = e.NewValue.ToString();
                SendSliderValue(e.NewValue);
            }
    
            private async void initWebSocket()
            {
                // Have we connected yet?
                if (messageWebSocket == null)
                {
                    // Validating the URI is required since it was received from an untrusted source (user input). 
                    // The URI is validated by calling TryGetUri() that will return 'false' for strings that are not
                    // valid WebSocket URIs.
                    // Note that when enabling the text box users may provide URIs to machines on the intrAnet 
                    // or intErnet. In these cases the app requires the "Home or Work Networking" or 
                    // "Internet (Client)" capability respectively.
                    Uri server = new Uri("ws://10.0.100.170:9000/slider", UriKind.Absolute); ;
    
                    messageWebSocket = new MessageWebSocket();
                    messageWebSocket.Control.MessageType = SocketMessageType.Utf8;
                    messageWebSocket.MessageReceived += MessageReceived;
    
                    // Dispatch close event on UI thread. This allows us to avoid synchronizing access to messageWebSocket.
                    messageWebSocket.Closed += async (senderSocket, args) =>
                    {
                        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Closed(senderSocket, args));
                    };
    
                    await messageWebSocket.ConnectAsync(server);
                    messageWriter = new DataWriter(messageWebSocket.OutputStream);
    
                }



    Donnerstag, 9. April 2015 19:31
  • Hallo,

    es freut mich, das du den Fehler gefunden hast.

    Ich möchte dich nur noch auf einen tückischen Fehler hinweisen, was die Verwendung von async und await betrifft. Wenn du eine Methode als async void oder als async RückgabeTyp deklarierst, wird die Methode ausgeführt, der Aufrufer läuft jedoch asynchron dazu weiter.

    Bei Eventhandlern ist das kein Problem - dadurch bleibt die UI reaktionsfähig. Bei normalen Methoden jedoch kann leicht etwas in der Ausführung durch einander geraten.

    Deklariere daher den ValueChanged-Eventhandler als async und initWebSocket als async Task. Dann kannst du die Methode mittels await aufrufen.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 9. April 2015 20:28
  • Hallo Tom

    Wo finde ich mehr Infos zu diesem Thema async/await usw.?

    Denke das ist irgendwie analog zu Javascript und AJAX Calls?

    Aus der Elektronikwelt, aus der ich ursprünglich komme, hat async und sync eine ganz andere Bedeutung (o;

    Donnerstag, 9. April 2015 20:34
  • async und await ist nicht schnell abgetan, wenn man es wirklich verstehen will. Auch hat JavaScript lediglich die Ansätze eines richtigen Threading-Models, das von Windows ist da schon komplexer.
    Wie es in der Elektronic Welt mit sync und async genau aussieht weiß ich nicht, aber einen gemeinsamen Nenner werden sie sicherlich haben ;)

    Für den Einstieg ist der MSDN Artikel (inkl. Unterseiten) Asynchrone Programmierung mit Async und Await (C# und Visual Basic) sich ganz gut geeignet.

    Async und await sind zwar relativ einfach zu verwenden, aber nicht perfekt. Daher gilt auch zu beachten: Asynchrone Leistung: Leistungseinbußen aufgrund von „async“ und „await“


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Donnerstag, 9. April 2015 20:41
  • Eine sehr gute Erklärung der MSDN Artikel :-)

    Async und Sync in der Elektronikwelt/Kommunikationswelt sind verwirrender....z.B. sagt man, dass RS232 asynchron ist, PCIe synchron.

    Einerseits wird da unterschieden mit:

    Asynchron: sporadische Kommunikation, also RS232, Keyboard usw.

    Synchron: dauernder Datenstrom wie z.B. SPDIF Ausgang eines DAT Players

    Aber wiederum gibt es in der Hardwarewelt bei Interconnect zweier Komponenten die Bedeutung:

    Asynchron: Datentransfer mit Handshake, wie z.B. Centronics/LPT, da kann also der Empfänger blockieren, bis es weiter geht

    Synchron: Daten und Clock werden gemeinsam gesendet, wie z.B. SATA, PCIe, HDMI usw.

    Ich denke, ich muss mir mal eine gute Lektüre generell zu C# suchen, ein paar Konstrukte sind mir da noch ziemlich fremd (o; ....irgendwie ist das vom Konstrukt her eine Mischung aus C, PHP und C++...

    Bis vor 2 Wochen verwendete ich nur Assembler, Forth, Postscript, Verilog, C, PHP, Javascript und Python (o;

    Donnerstag, 9. April 2015 21:24