Serge schrieb:
> Auf Form1 ist ein textBox- und ein serialPort1 Objekt.
> Kommt ein Zeichen von der seriellen Schnittstelle, so soll es gleich in
> der Textbox erscheinen. Also verwende ich das dafür vorgesehene Event.
>
> Der Witz ist nun, wenn ein Zeichen von der seriellen Schnittstelle
> kommt, dann erhalte ich eine Fehlermeldung.
Das ist normal, die Events des Serialport erfolgen im Kontext
zusätzlicher Threads, innerhalb solcher Events darf man nicht am GUI
rumpfuschen, denn dieses ist nicht thread-sicher programmiert.
Die Lösung ist, die Events mit dem Main-Thread, der das GUI "betreibt"
zu synchronisieren. Dafür bieten freundlicherweise fast alle
GUI-Elemente die Methoden InvokeRequired, Invoke und BeginInvoke an.
Du brauchst also pro SerialPort-Event zwei Eventhandler, einen, der
asynchron im Kontext des SerialPort-Threads läuft (und ggf. eine
Vorverarbeitung der gelieferten Daten leistet) und einen zweiten, der
synchron im Kontext des Haupthreads läuft.
>
1 | >
|
2 | > private void serialPort1_DataReceived(object sender,
|
3 | > System.IO.Ports.SerialDataReceivedEventArgs e)
|
4 | > {
|
5 | > textBox1.AppendText(serialPort1.ReadChar().ToString());
|
6 | > }
|
7 | >
|
8 | >
|
Das ist sowieso ziemlicher Mist, selbst wenn die Events des SerialPort
von Hause aus synchronisiert wären.
Das kann nur dann funktionieren, wenn nur alle Jubeljahre mal ein
einzelnes Zeichen eintrödelt. Sobald der Sender schneller sendet, als
der ReadTimeout bestimmt, geht das Konstrukt den Bach runter. Oder auch
dann, wenn der ReadTimeout zwar senderseitig nicht unterschritten wird,
aber die Verarbeitung des Zeichens länger dauert und deshalb das nächste
Zeichen vom Sender schon da ist, bevor die Verarbeitung des aktuellen
abgeschlossen ist.
Aber tun wir mal so, als wären diese Gegenindikationen nicht gegeben und
die Routine würde auf Grund der Randbedingungen prinzipiell
funktionieren können, das einzige Problem wäre also wirklich nur die
Thread-Synchronisation. Dann wäre die Lösung:
>
1 | private delegate void SerialPortCharReceivedHandler(object sender, char data);
|
2 |
|
3 | private SerialPortCharReceivedSync(object sender, char data)
|
4 | {
|
5 | textBox1.AppendText(data.ToString());
|
6 | }
|
7 |
|
8 | private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
|
9 | {
|
10 | char data=(sender as SerialPort).ReadChar();
|
11 | Invoke(new SerialPortCharReceivedHandler(SerialPortCharReceivedSync, new object[] {sender,data});
|
12 | }
|
13 | >
|