Laden...

[Erledigt]IndexOutOfRange Exception bei Button.Visible Änderung

Erstellt von 123thomas vor 7 Jahren Letzter Beitrag vor 7 Jahren 2.268 Views
1
123thomas Themenstarter:in
124 Beiträge seit 2012
vor 7 Jahren
[Erledigt]IndexOutOfRange Exception bei Button.Visible Änderung

Hallo,

ich habe ein Problem unzwar habe ich ein Programm, welches GPS Daten über die COM Schnittstelle einliest, diese dann verarbeitet und in einen dataGridView ausgibt. Das funktioniert auch soweit. Aber wenn ich die Verarbeitung starte und das dataGridView dann ca. 2 Einträge habe und dann Stoppe stürtz das Programm bei folgender Zeile ab:

bnt_stop.Visible = false;

mit folgendem Fehler:> Fehlermeldung:

Ein Ausnahmefehler des Typs "System.IndexOutOfRangeException" ist in System.Windows.Forms.dll aufgetreten.

Zusätzliche Informationen: Der Index -1 hat keinen Wert.

Mein Problem ist, dass ich keine Ahnung habe was bei dem Button, der übrigens mit dem Designer erstellt wurde, der Index sein soll.

Was ich bis jetzt herausgefunden habe ist, dass wenn ich das dataGridView nicht fülle(bzw. keine Daten über die Com Schnittstelle empfange) ich auch kein Absturz habe.

hier der Code der Buttons bnt_start und bnt_stop:

private void bnt_stop_Click(object sender, EventArgs e)
        {
            //try
            //{
                
                //try
                //{
                    bnt_start.Visible = true;
                    //new Fehler("" + bnt_Stop.ToString()+ "|" + bnt_Stop.Controls.ToString());
                   [COLOR] bnt_stop.Visible[/COLOR] = false;
                //}
                //catch { throw new ArgumentException("Button Visible Fehler"); }
                log.LoggingAktiv = false;
                ToolstripCOMPort(false);
                serialPort.CloseCOMPort();
                
            /*}
            catch (Exception ex)
            {
                //toolStripStatusLabel2.Text = ex.Message;
                bnt_stop.Visible = true;
                bnt_start.Visible = false;
                log.LoggingAktiv = true;
                ToolstripCOMPort(true);
                new Fehler("Stop Button konnte nicht komplett verarbeitet werden. Fehlertext: " + ex.Message);
                MessageBox.Show("Fehler beim Schließen des COM Ports", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }*/

        }
 private void bnt_start_Click(object sender, EventArgs e)
        {
            try
            {
                string settings = loadSettings();
                if (settings != null && settings != "")
                {
                    serialPort = new SerialPortverwal(settings);
                }
                serialPort.DataReceived += serialPort_DataReceived;
                bnt_stop.Visible = true;
                bnt_start.Visible = false;
                log.LoggingAktiv = true;
                ToolstripCOMPort(true);
                Properties.Settings.Default.positionGPSData = 0;
                Properties.Settings.Default.Save();
                listGPSData = new List<GPSData>();
                dataGridView1.DataSource = new List<GPSData>();
                dataGridView1.DataSource = listGPSData;
            }
            catch(Exception ex)
            {
                //toolStripStatusLabel2.Text = ex.Message;
                bnt_stop.Visible = false;
                bnt_start.Visible = true;
                log.LoggingAktiv = false;
                ToolstripCOMPort(false);
                if (serialPort != null)
                    if (serialPort.isOpen)
                        serialPort.CloseCOMPort();
                new Fehler("Start Button konnte nicht komplett verarbeitet werden. Fehlertext: " + ex.Message);
                MessageBox.Show("Fehler beim Öffnen des COM Ports", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    
            }
        }

Hier die Oberfläche, damit man sich es besser vorstellen kann.:

Wenn ihr noch mehr Infos braucht dann bitte melden.
Gruß Thomas

771 Beiträge seit 2009
vor 7 Jahren

Du versuchst den Button unsichtbar zu schalten, während der Eventhandler läuft?!
Teste mal, ob "Enabled = false" wenigstens funktioniert.

Ansonsten hilft evtl. [FAQ] Bestimmte Aktionen bis nach der laufenden GUI-Event-Behandlung verzögern

3.170 Beiträge seit 2006
vor 7 Jahren

Hallo,

die Zeile ist ja die erste in Deinem catch-Block. Bist Du sicher, dass die IndexOutOfRange nicht genau die Exception ist, die Du gerade fängst?

Gruß, MarsStein

Edit: Oh, die Exception fliegt ja im Click auf den Stop-Button - das habe ich erst nach Deinem Edit gesehen...

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

1
123thomas Themenstarter:in
124 Beiträge seit 2012
vor 7 Jahren

@Cat

Das habe ich auch erst gedacht, aber beim bnt_start ist da das selbe und dort funktoniert alles wie es soll und dann habe ich mir das Beispiel in kurz nachgebaut:

private void button1_Click(object sender, EventArgs e)
        {
            button1.Visible = false;
            button2.Visible = true;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            button2.Visible = false;
            button1.Visible = true;
        }

Dort funktioniert alles.

Wenn ich beide Buttons mit Enable true und false beschreiben dann bleibt der Startbutton immer da und wird nur ausgegraut. Wenn ich nur den Stop Button von Visible durch bnt_stop.Enabled = false; ersetzte passiert das gleiche wie in ersten Post. An der Zeile wird die Exception geworfen.

Ich glaube so langsam das es irgendwie mit dem dataGridView zusammen hängt kann aber nicht sagen wie.

EDIT:Auch mit Invoke stürtz es bei Visible ab

public static void ButtonInvoke(Button _Button, bool _Visible, bool _Enable)
        {
            _Button.Invoke(new EventHandler(delegate
            {
                _Button.Visible = _Visible;
                _Button.Enabled = _Enable;
            }));
        }
C
2.121 Beiträge seit 2010
vor 7 Jahren

Solche komischen Fehler kommen mir bekannt vor. Auch mit DataGridView, auch wenn die Daten drin sich ändern. Meine damalige Vermutung war, es passiert wenn sich die Daten ändern und man währenddessen im Grid herum klickt. Vielleicht klickt man ein Item an an dessen Stelle im nächsten Moment keins mehr ist, oder es ändert sich im ungünstigen Moment. Und dann kommt etwas durcheinander.
Eine Lösung konnte ich nicht finden, war auch "nicht so schlimm" laut den Benutzern. Das löst nun nichts aber könnte dir beim Nachvollziehen helfen.

3.170 Beiträge seit 2006
vor 7 Jahren

Hallo,

was sagt denn der Stacktrace wenn die Exception fliegt?

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

4.931 Beiträge seit 2008
vor 7 Jahren

Wie sieht denn deine "serialPort_DataReceived"-Methode aus? Wie synchronisierst du dort die Daten (denn das Event wird aus einem Nicht-UI-Thread heraus aufgerufen und List<T> ist nicht thread-safe)?

Falls meine Vermutung richtig ist, dann kannst du dir dazu auch mal Threadsicherer Zugriff auf ObservableCollection und LINQ durchlesen.

1
123thomas Themenstarter:in
124 Beiträge seit 2012
vor 7 Jahren

Meine DataReceived Methode sieht wie folgt aus:

void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            System.IO.Ports.SerialPort spL = (System.IO.Ports.SerialPort)sender;
            string received = spL.ReadExisting();
            List<string> list = received.Split('\n').ToList<string>();
            while (list.Contains(""))
            {
                list.Remove("");
            }
            listView1.Invoke((Action)(() => listViewadapt.setGPSData(GPSDataConverter.convertNmeaToGPSData(list, listGPSData))));
            foreach(string line in list)
            {
                log.write(line);
            }
        }

Durch das Invoke bin ich doch thread-safe oder?

@MarsStein
Den Stacktrace kenne ich nicht, habe aber gerade danach gegooglet. Den muss ich dann erst einprogrammieren oder zeigt VS Express 2013 den direkt an?

Gruß und danke schonmal für die Hilfe

3.170 Beiträge seit 2006
vor 7 Jahren

Hallo,

der Stacktrace wird beim Debuggen angeigt (falls bei Dir nicht, kannst Du das Fenster über das Debug-Menü einblenden DEBUG->Windows->Call Stack).

Zusätzlich steckt der Stacktrace aber auch_ in der Exception selbst_ als Property StackTrace.

Edit: In der Exception steckt der relevante Callstack beim Auslösen der Exception (auch wenn sich da nicht immer was sinnvolles findet).
Das muss nicht derselbe sein, wie in dem Debug-Fenster. In letzterem kannst Du während des Debuggens immer den aktuellen Callstack sehen.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

16.806 Beiträge seit 2008
vor 7 Jahren

Durch das Invoke bin ich doch thread-safe oder?

Nö. Invoke sorgt nur dafür, dass Du etwas im UI-Thread ausführst.
Das hat nichts mit Thread-Synchronisation zutun.

Du gibst die Referenz von list weiter, bearbeitest sie dann wohl gleichzeitig in zwei Threads - ohne lock().
Entweder als Listen-Kopie übergeben (list.Tolist()) oder entsprechend Thread-Safe arbeiten.

1
123thomas Themenstarter:in
124 Beiträge seit 2012
vor 7 Jahren

Du gibst die Referenz von list weiter, bearbeitest sie dann wohl gleichzeitig in zwei Threads - ohne lock().
Entweder als Listen-Kopie übergeben (list.Tolist()) oder entsprechend Thread-Safe arbeiten.

Okay das wird es gewesen sein. Zumindest hatte ich schon lange keine Abstürze mehr.