Forum: PC-Programmierung Auf ein Ereignis warten ( Visual C# 2005 Express Edition)


von Tobias (Gast)


Lesenswert?

Hallo,

ich möchte ein Programm schreiben das Daten über die RS232 an einenen 
Prozessor sendet und dann auf die Antwort wartet. Dann erst soll das 
Programm weiter machen.
Ich habe bereits ein Programm was Daten sendet und auch empfangen kann. 
Über 'serialPort1_DataReceived()' inkl. Threadsicherer Verarbeitung 
klappt das ganze auch soweit. Nur bin ich jetzt mit meinem 
(Anfänger)-Latein am Ende.
Ich möchte im Programm sicher stellen, dass die Antwort auf meine 
Anfrage auch gekommen ist, bevor ich weiter mache.
Es wird wohl irgendwie über Treads gehen. Nur wie kann ich den Thread in 
dem alles läuft anhalten?

Der Ablauf soll in etwa so sein:

1) serialPort1.Write("Hallo");

2) (Warten auf Antwort in 'serialPort1_DataReceived()')

3) Antwort auswerten

4) if(Antwort == ok)
     serialPort1.Write("123");

5) weiter mit 2)

Zur Zeit schreibe ich die Anfragen in einer Funktion untereinander weg 
und werte sie in DataReceived() aus.
Nur sende ich ja die Anfragen hintereinander weg. Und das soll nicht 
sein.

Kann mir da jemand weiterhelfen.

Danke und Grüße
Tobias

von Christian R. (supachris)


Lesenswert?

Thread ist schon richtig. Dann musst du zuerst ein Event registrieren, 
also der SerialPort komponente bekannt geben, welches Event das 
Empfangs-Event ist. Und dann im Thread einfach WaitOne() mit diesem 
Event benutzen. Dann bleibt der Thread da stehn und macht erst weiter, 
wenn das Event eintritt. Am sinnvollsten nimmt man dafür ein Autoreset 
Event.

von Tobias (Gast)


Lesenswert?

Hallo Christian,

das klingt ja ganz einfach und genau nach dem was ich suche.
Nur wie mache ich das Code-Technisch?
Vom logischen verstehe ich deine Antwort zwar, kann sie aber leider 
nicht umsetzen :-(
Kannst Du mir da noch ein wenig unter die Arme greifen?

Tobias

von Christian R. (supachris)


Lesenswert?

Uff....also Beispielcode hab ich keinen. Einer meiner Hiwis macht das 
momentan für einen CAN-Adapter von IXXAT. Da guck ich immer mal, wie das 
geht.
Zuerst solltest du einfach einen Thread erstellen, wie, steht ja in der 
MSDN Hilfe.
Dann musst du deine Serialport-Klasse hernehmen, wenn´s die aus dem .NET 
Framework ist, gibts ja auch die Anleitung im MSDN. Da halt beim 
Initialisieren das Event registrieren. Das gings mit dem AutoReset 
Event. Such halt mal nach den Begriffen in der MSDN Hilfe. Da findest du 
immer den Beispielcode. im Thread dann einfach WaitOne() aufrufen, als 
Übergabeparameter das Event. Viel mehr kann ich dir leider nicht sagen.
Vielleicht solltest du erst mal einen ganz einfachen Thread 
programmieren, und z.b. mit Thread.Sleep(2000) alle 2000ms irgend ne 
Meldung oder sowas erzeugen, damit du den Mechanismus verstehst.

von Torq (Gast)


Lesenswert?

Es geht moeglicherweise noch etwas einfacher. Ich habe das eben so 
geloest, dass ich mir in Thread1 eine Methode definiert habe:

private string serialPort1.sendCommand()

Im Thread dieser Methode wird an den serialPort ein Textstring 
geschickt, und laengstenfalls zwei Sekunden auf Antwort gewartet; 
Rueckgabewert ist entweder die Antwort des Ports oder eine 
Fehlermeldung.

Jetzt ists aber so, dass die Variable, die die Antwort des SerialPorts 
enthalten soll, Teil von Thread1 ist, waehrend der serialPort einen 
eigenen Thread (Thread2) darstellt. Aergerlicherweise wird das Event von 
Thread2 erst dann in die Variable geschrieben, wenn Thread1 nicht mehr 
wartet. Ich wollte aber, dass Thread2 die Antwort direkt in die Variable 
schreibt, sobald sie kommt. Die Loesung ist die Befehlszeile:

Application.DoEvents();

Damit haelt Thread1 an und arbeitet alle anderen Events ab, bevor beim 
urspruenglichen Event weitergemacht wird. Komplett sieht die Loesung so 
aus:


  private string serialPortSendCommand(SerialPort p, String str) {
    int timer = 0;
    p.Write(str);

    while(answer == "" && timer < 40) {
      System.Threading.Thread.Sleep(50);
      Application.DoEvents();
      timer++;
    }
    if (timer > 30) return "Error! No Signal!";
    else return answer;
  }

von Peter II (Gast)


Lesenswert?

wozu überhaupt threads?


 serialPort1.Write("Hallo");
 serialPort1.Read();

fertig. Die Timeouts kann ma ja auch festlegen - ist das zu einfach oder 
überseh ich was?

von Sam .. (sam1994)


Lesenswert?

Peter II schrieb:
> wozu überhaupt threads?
>
>
>  serialPort1.Write("Hallo");
>  serialPort1.Read();
>
> fertig. Die Timeouts kann ma ja auch festlegen - ist das zu einfach oder
> überseh ich was?

Das ist die einfachste Variante. Eleganter ist das über Events zu lösen, 
da das ganze Programm da nicht an einer Stelle wartet. Threads nimmt man 
eher bei Asyncronen Aufgaben.

von Peter II (Gast)


Lesenswert?

Samuel K. schrieb:
> Das ist die einfachste Variante. Eleganter ist das über Events zu lösen,
> da das ganze Programm da nicht an einer Stelle wartet.

man kann aber das senden und empfangen komplett im Thread machen. damit 
ist auch beim Senden die GUI noch aktiv.

von Sam .. (sam1994)


Lesenswert?

das geht auch. Ich persönlich würde es über Events machen und eine 
Variable setzen, ob die Anfrage bestätigt worden ist oder nicht. Bei 
Events ist die GUI übrigens auch noch aktiv.

von Peter II (Gast)


Lesenswert?

Samuel K. schrieb:
> Bei Events ist die GUI übrigens auch noch aktiv.
Dann hast du das Problem aber auch noch beim Senden. Das Blockiert bis 
alle datenn in den Puffer geschrieben sind.

von Sam .. (sam1994)


Lesenswert?

Das dauert aber wenn man nur Steuerbefehle sendert nicht so lang.

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.