Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
[Erledigt]IndexOutOfRange Exception bei Button.Visible Änderung
123thomas
myCSharp.de - Member



Dabei seit:
Beiträge: 124

Themenstarter:

[Erledigt]IndexOutOfRange Exception bei Button.Visible Änderung

beantworten | zitieren | melden

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:
Fehler
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
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von 123thomas am .
Attachments
private Nachricht | Beiträge des Benutzers
Cat
myCSharp.de - Member

Avatar #avatar-3070.jpg


Dabei seit:
Beiträge: 771

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
MarsStein
myCSharp.de - Experte

Avatar #avatar-3191.gif


Dabei seit:
Beiträge: 3.170
Herkunft: Trier -> München

beantworten | zitieren | melden

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...
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von MarsStein am .
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
private Nachricht | Beiträge des Benutzers
123thomas
myCSharp.de - Member



Dabei seit:
Beiträge: 124

Themenstarter:

beantworten | zitieren | melden

@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;
            }));
        }
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von 123thomas am .
private Nachricht | Beiträge des Benutzers
chilic
myCSharp.de - Experte



Dabei seit:
Beiträge: 2.102

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
MarsStein
myCSharp.de - Experte

Avatar #avatar-3191.gif


Dabei seit:
Beiträge: 3.170
Herkunft: Trier -> München

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.317

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
123thomas
myCSharp.de - Member



Dabei seit:
Beiträge: 124

Themenstarter:

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
MarsStein
myCSharp.de - Experte

Avatar #avatar-3191.gif


Dabei seit:
Beiträge: 3.170
Herkunft: Trier -> München

beantworten | zitieren | melden

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
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von MarsStein am .
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.751

beantworten | zitieren | melden

Zitat
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.
private Nachricht | Beiträge des Benutzers
123thomas
myCSharp.de - Member



Dabei seit:
Beiträge: 124

Themenstarter:

beantworten | zitieren | melden

Zitat von Abt
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.
private Nachricht | Beiträge des Benutzers