Forum: PC-Programmierung C# Problem mit SerialDataReceivedEventHandler


von gremlin (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein großes Problem in C# dass ich jetzt nach einem Tag 
recherchieren immer noch nicht lösen konnte.

Problem:

Ich kommuniziere mit einem MC über ein C# Programm. Meinen Port habe ich 
soweit festgelegt und die Kommunikation funktioniert problemlos.
1
port.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

Steht in meiner form1() Funktion und in sp_DataReceived wird der 
empfangene Text in einer Textbox ausgegeben.

Nun möchte ich vom MC mehrere Sachen nacheinander in einer Funktion die 
durch einen Button_Click aufgerufen wird abfragen.
Ich sende dem MC meinen String auf den er die angeforderten Daten 
schickt (Habe ich mit einem PortMonitor überprüft.)

Ich lasse das C# Programm in einer for Schleife etwas warten bis die 
Daten übetragen sein müssten. Genau jetzt wäre ja der Punkt dass mein 
EventHandler die sp_dataReceived aufrufen müsste. Das macht er leider 
nicht. Erst wenn die Funktion zu Ende ist wird die sp_dataReceived 
einmal aufgerufen und der letzte gesendete Wert geschrieben.

Ich habe
1
port.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
 auch schonmal direkt in die Funktion geschrieben, das hat auch nichts 
genutzt. Achja, der Port war natürlich auf Open.

Ich bin für jede Hilfe dankbar, ich bin nämlich langsam am verzweifeln.

Grüße
Simon

von Peter II (Gast)


Lesenswert?

gremlin schrieb:
> Nun möchte ich vom MC mehrere Sachen nacheinander in einer Funktion die
> durch einen Button_Click aufgerufen wird abfragen.
> Ich sende dem MC meinen String auf den er die angeforderten Daten
> schickt (Habe ich mit einem PortMonitor überprüft.)

wenn ich das richtig verstande haben schickt du etwas hin und erwartest 
eine Antwort?

Wenn ja warum programmierst du es dann nicht so, sende etwas mit 
Port.Write und mache danach ein Port.Read - dazu braucht man keinen 
Eventhandler.

von gremlin (Gast)


Lesenswert?

Bis etwas zurück kommt dauert es aber ja um die 1 Sekunde, ein 
Thread.Sleep würde das ganze Programm ne Sekunde lahm legen, gibts dan 
noch ne ander möglichkeit?

von Arc N. (arc)


Lesenswert?

gremlin schrieb:
> Bis etwas zurück kommt dauert es aber ja um die 1 Sekunde, ein
> Thread.Sleep würde das ganze Programm ne Sekunde lahm legen, gibts dan
> noch ne ander möglichkeit?

Angedeutet wurde es schon von Peter II...
Die Sende- und Empfangsroutine in einen BackgroundWorker und die 
Timeouts des SerialPorts passend einstellen

http://msdn.microsoft.com/de-de/library/system.componentmodel.backgroundworker.aspx
http://stackoverflow.com/questions/1197246/backgroundworker-thread-used-for-serial-port-data-processing-throwing-this-backg

oder
die Sachen (fast) ohne Threads, Thread.Sleep etc. schreiben.
Stichwort: Zustandsmaschine
In Button_Click wird der erste Befehl an den Controller gesendet (und 
z.B. ein Timer gestartet, damit festgestellt werden kann, dass nichts 
empfangen wurde und um die Zustandsmaschine wieder in einen definierten 
Zustand zu bringen), in sp_DataReceived wird überprüft ob die Antwort 
vollständig ist,
wenn ja, wird der nächste Befehl gesendet (und irgendwas mit den Daten 
gemacht), wenn nein, werden die empfangenen Daten den bisher empfangenen 
hinzugefügt...

p.s. Newline 
http://msdn.microsoft.com/de-de/library/system.io.ports.serialport.newline.aspx 
passend gesetzt?

von Oliver R. (superberti)


Lesenswert?

Hi,

> Hallo zusammen,
>
> ich habe ein großes Problem in C# dass ich jetzt nach einem Tag
> recherchieren immer noch nicht lösen konnte.
[...]
>
> Ich lasse das C# Programm in einer for Schleife etwas warten bis die
> Daten übetragen sein müssten. Genau jetzt wäre ja der Punkt dass mein
> EventHandler die sp_dataReceived aufrufen müsste. Das macht er leider
> nicht. Erst wenn die Funktion zu Ende ist wird die sp_dataReceived
> einmal aufgerufen und der letzte gesendete Wert geschrieben.

Du musst Dir klarmachen, dass Deine Oberfläche standardmäßig immer nur 
Single-Threaded ist, egal ob WPF oder Windows-Forms.
Wenn Du nun eine busy-loop (Deine for-Schleife) ausführst, dann kann 
niemand Deinen seriellen Event bearbeiten, da der Dispatcher erst wieder 
an die Reihe kommt, wenn Dein Programm idle ist. Es gibt zwar 
Möglichkeiten den Dispatcher per Hand aus Deiner Schleife aufzurufen 
(DoEvents etc.), das willst Du aber nicht wirklich.
Wie hier schon geschrieben wurde sollte man also entweder blockierende 
Reads mit Timeout in einem eigenen Thread benutzen, oder aber im 
Eventhandler die Daten irgendwo zwischenspeichern, bis die komplette 
Antwort eingelesen wurde und dann darauf reagieren (je nach Timing kann 
es auch mehrere Events geben, bis Deine Nachricht vom MC komplett da 
ist).

Gruß,

Oliver

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
Noch kein Account? Hier anmelden.