Hallo zusammen. Ich habe ein kleines Programm in C# (WPF) geschrieben, welches aus einem Hauptfenster und einem untergeordneten Fenster besteht (dieses wird über einen Button aus dem Hauptfenster heraus geöffnet). In diesem untergeorneten Fenster wird ein Objekt der Klasse "SerialPort" instanziert und im Konstruktor des Fensters die serielle Schnittstelle geöffnet und ein Event auf den Empfang eines Bytes auf dieses Objekt aboniert. Im dem Eventhandler (wenn Daten empfangen wurden) wird anschließend über eine TextBox eine Ausgabe in dem untergeorneten Fenster gemacht ("Daten empfangen"). Das klappt auch alles wunderbar, allerdings nur bei ersten Öffnen des untergeorneten Fensters. Wenn ich dieses schließe und danach wieder (aus dem Hauptfenster heraus) öffne, wird über die TextBox nur noch zufällig beim Empfang von einem Byte eine Ausgabe getätigt. Schließe ich die ganze Anwendung und starte sie neu, funktioniert alles wieder wie erwartet. Aber nur solange ich das untergeordnete Fenster nicht schließe und wieder öffne. Ich kann mir beim besten Willen nicht erklären, woher dieses Verhalten herkommt. Kann es sein, dass der Thread, der die serielle Schnittstelle ausliest, bei Schließen des untergeordneten Fensters nicht mit beendet wird und es dann beim erneuten Start dieses Fernsters zu Problemen führt? Im Anhang habe ich mal das Programm gepackt. Ich hoffe Ihr könnt mir helfen. Vielen Dank im Vorraus.
1 | private void ButtonBeendenClick(object eventSender, RoutedEventArgs eventData) |
2 | {
|
3 | if (serialPort.IsOpen) |
4 | {
|
5 | serialPort.Close(); |
6 | }
|
7 | this.Close(); |
8 | }
|
Und wenn das Fenster anders geschlossen wird?
1 | private void OnClosed(object sender, CancelEventArgs e) |
2 | {
|
3 | serialPort.DataReceived -= SerialPortDataReceived; |
4 | |
5 | if(serialPort.IsOpen) serialPort.Close(); |
6 | }
|
*******************
1 | private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) |
2 | {
|
3 | // Empfangene Daten aufbereiten und in diesem Fenster ausgeben
|
4 | Dispatcher.Invoke(new Action(() => |
5 | {
|
6 | // Wenn 1 Byte empfangen wurde, wird etwas im Fenster geändert
|
7 | if (serialPort.BytesToRead == 1) |
8 | |
9 | ...
|
Warum gehst du davon aus, dass genau 1 Byte empfangen wird (==1)? Der Handler wird nicht für jedes einzelne Byte aufgerufen. Und bei Invoke kann es einen Deadlock geben, wenn du den Port schließen willst.
1 | Dispatcher.BeginInvoke(new Action(() => |
2 | {
|
3 | ...
|
*******************
1 | // Hintergrund weiß färben
|
2 | textBox1.Background = Brushes.White; |
3 | // Text löschen
|
4 | textBox1.Text = ""; |
5 | |
6 | ...
|
7 | |
8 | // Hintergrund grün färben
|
9 | textBox1.Background = Brushes.Lime; |
10 | // Text ausgeben
|
11 | textBox1.Text = "Daten Empfangen"; |
12 | // Empfangspuffer löschen
|
13 | serialPort.DiscardInBuffer(); |
14 | |
15 | ...
|
16 | |
17 | // Serielle Schnittstelle schließen, falls diese offen ist
|
18 | if (serialPort.IsOpen) |
19 | {
|
20 | serialPort.Close(); |
21 | }
|
22 | // Fenster schliesen
|
23 | this.Close(); |
99% der Kommentare in deinem Code sind nicht nur überflüssig, sondern verschlechtern die Lesbarkeit ... SerialPort und die Kommunikation gehören nicht in eine Fensterklasse. Verwende zumindest eine eigene Klasse und z.B. Events (über die dein Fenster aufbereitete Daten zur Darstellung erhält).
Danke für die Antwort. Das mit dem Kündigen des Events habe ich vergessen. Mit dieser Änderung geht es aber jetzt. AmanitaMuscaria schrieb: > 99% der Kommentare in deinem Code sind nicht nur überflüssig, sondern > verschlechtern die Lesbarkeit ... Das sehe ich anders. Im Programmcode werden Kommentare ja grün dargestellt und heben sich somit vom Funktionscode deutlich ab. Zudem gibt es im Code meiner Meinung nach keine überflüssigen Kommentare. Für jemanden, der gerade mit C# anfängt, sind auch solche Kommentare ggf. sehr hilfreich.
:
Bearbeitet durch User
Daniel M. schrieb: > gibt es im Code meiner Meinung nach keine überflüssigen Kommentare. Für > jemanden, der gerade mit C# anfängt, sind auch solche Kommentare ggf. > sehr hilfreich. Für Anfänger richtig, solange es zweckmässig und nicht übertrieben ist. Nach etwas Routine im Programmieren werden auch die Kommentare weniger. Falsch ist, unzureichende oder gar keine Kommentare zu schreiben, weil man nach Jahren den eigenen Code nicht mehr versteht. Dann war die Mühe beim Schreiben von seitenweise Quellcode reine Zeitverschwendung. Manchmal sind Kommenatre aber völlig überflüssig, wie hier: printf("Stackpointer=%x\n",iSPTR); //Leckeres Pilz-Omelett: 5 Eier, printf("Datensegment=%x\n",iDSEG); //2 Fliegenpilze, 300g Mehl
Daniel M. schrieb: > Das mit dem Kündigen des Events habe ich vergessen. Mit dieser Änderung > geht es aber jetzt. Gut, freut mich. Manchmal hängt man bei solchen Dingen ewig fest. Ich würde aber empfehlen, auch die anderen Sachen zu ändern, falls du es noch nicht gemacht hast: Aufräumen in OnClosed des zweiten Fensters: Der Button ist ja nicht die einzige Art, das Fenster zu schließen; verwendet man die "falsche", gibt es Probleme, weil der entsprechende Code nicht ausgeführt wird. BeginInvoke statt Invoke, da sonst unter ungünstigen Umständen im Zusammenspiel mit SerialPort dein Programm einfriert. Die Hintergründe sind etwas kompliziert, aber wie gesagt, es kann zu einem Deadlock kommen. Wenn das Programm umfangreicher werden sollte, könnte man SerialPort und die ganze Kommunikation aus dem Fenster herausnehmen. Puristen würden vermutlich anmerken, dass so etwas "nie" direkt in den Code der Fensterklasse bzw. überhaupt die GUI gehört, aber bei einem kleinen Programm muss man meiner Meinung nach nicht päpstlicher als der Papst sein. > Für jemanden, der gerade mit C# anfängt, sind auch solche Kommentare ggf. > sehr hilfreich. Ja, ein Anfänger mag ein paar Kommentare mehr schreiben bzw. gebrauchen können, das ist nicht falsch. Ich hatte das ohne weitere Erklärung so hingeworfen. Aber generell sollte der Code (wenn möglich) für sich selbst sprechen - durch seine Struktur und die Namen von Funktionen und Variablen etc. Für die Ausnahmen gibt es dann Kommentare. Außerdem kann man damit natürlich Funktionen bzw. Gruppen von Ausdrücken zusammenfassend beschreiben, auf Gefahren hinweisen u.a. Was sie nicht sollen: Verwirren (z.B. durch Mehrdeutigkeit) oder - im anderen Extrem - etwas Offensichtliches wiederholen. > Zudem gibt es im Code meiner Meinung nach keine überflüssigen Kommentare. Eher sogar recht viele - wobei ich das, wenn du wirklich für absolute Anfänger verständlich schreiben willst, evtl. etwas abschwächen muss. Aber hier mal ein typisches Beispiel, das definitiv auch für Anfänger gilt: // Hintergrund weiß färben textBox1.Background = Brushes.White; Der Kommentar ist gut gemeint, aber sinnlos, denn da steht bereits "Hintergrund = weiß" - also erhöht er nur das "Rauschen". Andererseits hast du die Textbox nicht umbenannt, so dass genau die einzige Frage, die man sich beim Betrachten des Codes irgendwann stellen könnte, nämlich welcher Hintergrund denn nun weiß wird, unbeantwortet bleibt (ohne nachzusehen). Soll bloß eine kleine Anregung zum Nachdenken sein, weil deine Antwort darauf schließen lässt, dass du dir einen solchen Kommentarstil - in der festen Überzeugung, dass er gut wäre -, angewöhnen könntest.
Daniel M. schrieb: > Im Programmcode werden Kommentare ja grün > dargestellt und heben sich somit vom Funktionscode deutlich ab. Das ändert sich, wenn man einen langen Quelltext mit vielen Kommentaren z.B. als Hilfe beim Programmieren im Windows Notepad öffnen möchte und dann nur noch schwarze Schrift auf weissem Hintergrund hat.
AmanitaMuscaria schrieb: > Gut, freut mich. Manchmal hängt man bei solchen Dingen ewig fest. Ich > würde aber empfehlen, auch die anderen Sachen zu ändern, falls du es > noch nicht gemacht hast: [...] > Wenn das Programm umfangreicher werden sollte, könnte man SerialPort und > die ganze Kommunikation aus dem Fenster herausnehmen. Puristen würden > vermutlich anmerken, dass so etwas "nie" direkt in den Code der > Fensterklasse bzw. überhaupt die GUI gehört, aber bei einem kleinen > Programm muss man meiner Meinung nach nicht päpstlicher als der Papst > sein. Der hier gepostete Code ist nur ein sehr kleiner Auszug aus einem doch sehr umfangreichen Programm, aber zur Demonstration des Problems, habe ich den Knackpunkt extrahiert. Die geamte Kommunikation habe ich nun in eine eigene Klasse ausgelagert und komplett von der Fenster-Klasse/ Benutzeroberfläche getrennt. Ist auch meiner Meinung nach deutlich sauberer so. Auch habe ich beide Möglichkeiten ein Fenster zu schließen behandelt: In allen Fällen wird das Event gekündigt. Da ich erst seit wenigen Wochen mit C# programmiere habe ich natürlich auch ein ganz anderes Gefühl für Kommentare, als ein Programmierer mit mehreren Jahren Berufserfahrung. Von daher wird sich das wohl im Laufe der Zeit noch ändern. Danke nochmals für die Antworten
Daniel M. schrieb: > Auch habe ich beide Möglichkeiten ein Fenster zu schließen behandelt: In > allen Fällen wird das Event gekündigt. Es gibt mehr, z.B. Alt-F4. Besser das Schließen-Event nutzen ...
Eisbeineis schrieb: > Es gibt mehr, z.B. Alt-F4. Besser das Schließen-Event nutzen ... Genau damit habe ich das auch gemacht, das Event wird ja immer aufgerufen wenn ein Fenster geschlossen wird.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.