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.
// Empfangene Daten aufbereiten und in diesem Fenster ausgeben
4
Dispatcher.Invoke(newAction(()=>
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(newAction(()=>
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.
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.