Laden...

Merkwürdiges Verhalten bei DataReceived

Erstellt von Daniel83 vor 16 Jahren Letzter Beitrag vor 16 Jahren 4.127 Views
D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 16 Jahren
Merkwürdiges Verhalten bei DataReceived

Hallo zusammen

Ich habe ein unerklärliches Verhalten in folgendem Aufruf.

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                string str = serialPort1.ReadExisting();
                //MessageBox.Show(str);
                BeginInvoke(new auswertung_delegate(auswertung), str);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            serialPort1.DiscardInBuffer();
        }

Wenn ich die hier auskommentierte Messagebox in den Ablauf hinein nehme, wird auf jedes Ereignis reagiert, also ich bekomme eine Ausgabe bei jedem mal wenn ich etwas schicke. Es reagiert wie erwartet. Alles ist gut, nehme ich nun die Messagebox heraus, so reagiert die Anwendung auf das erste Senden, und danach "beliebig". Beliebig heißt das mal nach jedem den 10. Senden, mal auf 2 aufeinander folgenden Sendungen.

Kann das mit Threading zu tun haben, oder ist es nur ein "Bug"?
Hat jemand eine Idee?

Danke schonmal

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Daniel83,

leider sind unerklärlichen Verhalten unerklärlich. Wenn es sich also hier wirklich um ein unerklärlichen Verhalten handeln würde, dann dürftest du nicht auf eine Antwort hoffen. 🙂

Klar ist, dass MessageBoxen den Ablauf der Anwendung - teilweise gravierend und unerwartet - ändern.

Beliebig heißt das mal nach jedem den 10. Senden, mal auf 2 aufeinander folgenden Sendungen.

Kannst du das bitte genauer erklären. Meinst du damit, dass du DataReceived nur einmal für zwei Datenpakete bekommst? Oder was anderes?

herbivore

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 16 Jahren

Habe die Anwendung auf einem Controlpanel, welchem ich zu Testzwecken über ein Programm auf dem PC via Comport telegramme zuschicke.
D.h. wenn ich von meinem PC das erste Telegramm schicke wird in jedem Fall richtig reagiert.
Habe ich die MessageBox im Code drin, wird auf jedes Protokol das ich sende erst mit der MessageBox und danach entsprechend der darauf folgenden Rutine reagiert.
Nehme ich die MessageBox heraus, so wird immer noch auf das erste Telegramm reagiert, (auch richtig) jedoch nicht unbedingt auf das darauf folgenden.
Also drücke ich in meinem Programm zum Senden wiederholt auf den Senden Button. Das Programm auf dem ControlPanel, also das welches diese Telegramme auswerten soll, reagiert dann nur noch manchmal. Dabei ist es egal, ob ich einige Sekunden Pause mache oder sehr schnell klicke.
Mal reagiert das Programm auf zwei aufeinander folgende Protokolle, mal macht es 10 oder 20 mal Senden gar nichts.

Ablauf:
Senden Reaktion
Protokoll Ja
Protokoll Nein
Protokoll Nein
Protokoll Nein
Protokoll Ja
Protokoll Ja
Protokoll Nein
...

Ich hoffe das ich so das Phänomen erschöpfend beschrieben habe.

S
8.746 Beiträge seit 2005
vor 16 Jahren

DiscardInBuffer() würd ich rausnehmen.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 16 Jahren

Danke sehr, das wars Tatsächlich. Löscht ReadExisting den Speicher selber? Also hab ich das dann doppelt gemacht?
Probiere gerade was passiert wenn sehr viele Daten kommen. Aber bis jetzt scheint es keinen überlauf oder so etwas zu geben.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 16 Jahren

Habe mal mit sehr viele Daten geschickt. Mein Code ist Offensichtlich nicht sehr perfomant, Habe aber dadurch feststellen können, Das der Code, je länger er arbeitet immer langsamer wird. Am Anfang wurden etwa 5-7 Auswertungen pro Sekunde durchgeführt, zum Schluss waren es nur noch 2 Auswertungen je Sekunde. Das spricht doch dafür, das sich ein "großer Berg" Daten angesammelt hat, den ich ja nun nicht mehr lösche(glaub ich). Die Hilfe konnte mir zu der Frage ob ich den Einlesespeicher lösche (mit readexisting) nicht weiter Helfen.
Ander zwischen Frage, ich gebe in eine Textbox mit Multiline und Scrollbar aus, ist da die Max Zeilenanzahl vorgegeben? Denn ich kann nur bis zu einer gewissen Stelle herunter scrollen, danach andert sich der inhalt nicht mehr, Obwohl er ja zumindest eine Andere Zeit anzeigen muss. Es sind bis dahin aber bestimmt einige hundert Zeilen.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 16 Jahren

Habe mal nachgeguckt. Ein string, zumindest war das bei C++ beim Ansi string so, hat 4GB kapazität, ich kan darstellen, also das was ich scrollen kann sind 951 Zeilen mit jeweils 63 Zeichen. Das sind aber wenn ein zeichen ein Byte hat nur ca 60kb, das ist ein bischen wenig finde ich, evtl. Zeilen Beschränkung?

S
8.746 Beiträge seit 2005
vor 16 Jahren

Löscht ReadExisting den Speicher selber? Also hab ich das dann doppelt gemacht?

Um Speicher und "Überläufe" mache dir mal keine Gedanken. Das Problem dürfte sein, dass du z.B. mit ReadExisting() z.B. 8 Bytes liest. Dann kommen z.B. nochmal 2 neue Bytes rein und bevor du die wieder abholst, hast du sie schon mit DiscardInBuffer() rausgeworfen. Du verlierst also Zeichen.

DiscardInBuffer() verwendet man eigentlich eher im Kontext des synchronen Modells (also ohne DataReceivedEvent) um sauber "aufzusetzen".

S
8.746 Beiträge seit 2005
vor 16 Jahren

Das Problem mit der Geschwindigkeit wird in deinem UI liegen. Zeig uns mal den Code der Funktion auswertung().

U
1.688 Beiträge seit 2007
vor 16 Jahren

Hallo Daniel83,

vielleicht schaust Du einfach mal in die TextBox-Dokumentation?

Außerdem ist es eine ganz schlechte Idee, zwei verschiedene Probleme in einem Thread zu behandeln.

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 16 Jahren
private void auswertung(string str)//str ist das eingelesene des COM Ports
        {
            string ausgabe="";

            Buffer += str;
            befehl tmp=new befehl();
            ausgabe = tmp.Befehl(Buffer);
            if (ausgabe != "" && ausgabe != "ungültig")
            {
                zähler++;
                tb_ausgabe.Text = tb_ausgabe.Text.Insert(17, "\r\n" + DateTime.Now 
                            + " : " + ausgabe + " von:" + tmp.ausgabe_Adr(Buffer) 
                            + zähler.ToString());
            }
            try
            {
                int start = tmp.get_Start(Buffer);
                int ende = tmp.get_Ende(Buffer);
                if (start >= 0 && ende > 0)
                {
                    if (ende - start + 1 <= Buffer.Length)
                    {
                        Buffer = Buffer.Remove(start, ende - start + 1);
                    }
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString()+"Fehler in auswertung");
            }
            
        }

public string Befehl(string eingang)//eingang alles im eigenen Eingabe Puffer
            {
                if (eingang.Length >= 5)
                {
                    get_Positions(eingang);
                    if (OK)
                    {
                        if (pos_befehl > 0)
                        {
                            return ausgabe_Befehl(eingang);
                        }
                    }
                    return "ungültig";
                }
                else
                {
                    return"";
                }
            }

private void get_Positions(string eingang)
            {
                pos_start = get_Start(eingang);
                if (pos_start >= 0)
                {
                    pos_ende = get_Ende(eingang);
                    if (pos_start >= 0 && pos_ende > 0)
                    {
                        pos_befehl = get_Befehl(eingang);
                        pos_adr = get_Adr(eingang);
                    }
                }
                if (pos_start >= 0 && pos_ende > 0 && pos_befehl > 0)
                {
                    OK = true;
                }
            }

public int get_Start(string eingang)
            {
                int pos = 0;
                try
                {
                    pos = eingang.IndexOf("\u0002");
                }
                catch (Exception e)
                {
                    //MessageBox.Show("index 0002 failed " + e.Message);
                    pos = -1;
                }

                return pos;
            }

private int get_Befehl(string info)
            {
                int pos = -1;
                try
                {
                    int min = 3;
                    int max = 6;
                    if (max >= info.Length)
                    {
                        for (; min < info.Length; min++)
                        {
                            for (int i = 0; i < moegl_Befehl.Length; i++)
                            {
                                if (info[min] == moegl_Befehl[i])
                                {
                                    return pos = min;
                                }
                            }
                        }
                    }
                    else
                    {
                        for (; min < max; min++)
                        {
                            for (int i = 0; i < moegl_Befehl.Length; i++)
                            {
                                if (info[min] == moegl_Befehl[i])
                                {
                                    return pos = min;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    //MessageBox.Show("  pos of Befehl Excep" + e);
                    pos = -1;
                }
                return pos;
            }

get_ende und get Adresse sind sehr ähnlich, deshalb Poste ich die der5 übersicht halber nicht

S
8.746 Beiträge seit 2005
vor 16 Jahren

Hast du mal probiert, den Text neu in die Textbox zu schreiben anstelle anzufügen? Wirds dann schneller?

D
Daniel83 Themenstarter:in
171 Beiträge seit 2008
vor 16 Jahren

Habe gerade 11.000 durchläufe gemacht, läuft mit ersetzen ohne Probleme und sehr schnell, ist jedoch nicht sinnvoll. gibt es eine effektive variante, also ohne ebiges schrittweise durchgehen, den TextBox Inhalt auf 500 Zeilen oder so zu begrenzen, Sowas könnte ich machen.
Aber ersetzen würde den ganzen Sinn zunichte machen, ich will ja zustände mitschreiben, die auch mal sehr schnell reinkommen können, wäre doof wenn man dann irgendwas wichtiges nicht sehen könnte.