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
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
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
@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;
}));
}
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.
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
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.
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
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
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.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Du gibst die Referenz von
list
weiter, bearbeitest sie dann wohl gleichzeitig in zwei Threads - ohnelock()
.
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.