Benutzer mit den meisten Antworten
RS-232 SerialPort - andere Möglichkeit zu warten?

Frage
-
Hallo Community,
ich habe ein Problem mit meiner RS-232 Anwendung.
Diese soll Bytearrays über RS232 verschicken und empfangen.
Hier meine Anwendung:using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO.Ports; using System.Threading; namespace RS232 { class Program { static int AnzahlGelesenerBytes = 1; static SerialPort ep = new SerialPort("COM8", 57600); static SerialPort sp = new SerialPort("COM1", 57600); static byte[] outpuffer = new byte[1024]; static void Main(string[] args) { byte[] inpuffer = new byte[1024]; ep.DataReceived +=new SerialDataReceivedEventHandler(DataReceivedHandler); inpuffer = ByteArrErzeugen(inpuffer); oeffnen(); Senden(inpuffer, sp); Warten(); vergleichen(inpuffer, outpuffer); Console.ReadLine(); } /// <summary> /// Simmuliert einen 1024 Byte großen Bytearray. /// </summary> /// <param name="inpuffer">Sendepuffer.</param> /// <returns>Sendepuffer.</returns> public static byte[] ByteArrErzeugen(byte[] inpuffer) { Random Rande = new Random(); for (int i = 0; i < 1024; i++) { inpuffer[i] = Convert.ToByte(Rande.Next(0, 99)); } return inpuffer; } /// <summary> /// Oeffnet die COM-Ports /// </summary> public static void oeffnen() { ep.Open(); sp.Open(); } /// <summary> /// Sendet 'inpuffer' an den Empfangsport /// </summary> /// <param name="inpuffer">Sendepuffer</param> /// <param name="ep">Empfangsport</param> public static void Senden(byte[] inpuffer, SerialPort ep) { sp.Write(inpuffer, 0, 1024); } /// <summary> /// Wartet bis alle Daten angekommen sind /// </summary> public static void Warten() { bool fertig = false; while (fertig == false) { if (AnzahlGelesenerBytes == 0) { fertig = true; } else { Thread.Sleep(1); } if (!ep.IsOpen) { Console.WriteLine("\nFehler bei der Uebertragung!"); Console.ReadLine(); } } AnzahlGelesenerBytes = 1; } /// <summary> /// Vergleicht die angekommenen Daten mit den gesendeten Daten. /// </summary> /// <param name="inpuffer">Sendepuffer.</param> /// <param name="outpuffer">Empfangspuffer.</param> public static void vergleichen(byte[] inpuffer, byte[] outpuffer) { bool fehler = false; for (int i = 0; i < 1024; i++) { if (inpuffer[i] != outpuffer[i]) { fehler = true; } } if (fehler == false) { Console.Write("Erfolgreich übertragen."); } } /// <summary> /// Hört den Empfangspuffer ab bis Daten angekommen sind. /// </summary> public static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { //Variable gibt an, an welche Stelle die ausgelesenen Bytes im Puffer geschrieben werden int lesestart = 0; while (AnzahlGelesenerBytes != 0) { //versuche die Anzahl der empfangenen Bytes zu ermitteln try { AnzahlGelesenerBytes = ep.Read(outpuffer, lesestart, 1024 - lesestart); } //wenn Timeout -> Anzahl = 0 catch (TimeoutException) { AnzahlGelesenerBytes = 0; } //lege nun die Variable Lesestart neu fest lesestart = lesestart + AnzahlGelesenerBytes; } } } }
Nun zu meiner Frage: Gibt es auch noch eine bessere Möglichkeit um zu warten ob alle Daten angekommen sind?
MFG Phil
Antworten
-
Hi xPhil,Thread.Sleep mit 1 ms ist keine gute Lösung, da die CPU sehr intensiv belastet wird. Besser ist es z.B. ein AutoResetEvent zu nutzen, welches in der DataReceivedHandler-Methode gesetzt wird, wenn alle Daten angekommen sind. Auf die Auslösung des AutResetEvent kann gewartet werden. Wie das Warten am besten implementiert wird, hängt vom Gesamtkonzept ab. Der Aufrufer arbeitet entweder synchron, asynchron oder mit Ereignisroutine (Endeereignis). Bei synchroner Arbeitsweise wartet die die aufgerufene Methode auf das AutoResetEvent. Bei asynchroner Arbeitsweise wird gestartet und ein Callback mitgegeben, welches für den Aufruf bei Übertragungsende genutzt wird. Für eine Ereignisauslösung ist die Nutzung des SerialPort zu kapseln und das Endeereignis wird entweder in der DataReceivedHandler-Methode ausgelöst oder ein Warten auf das AutoResetEvent löst das Endeereignis aus. In jedem Fall ist mit multithreading zu arbeiten, entweder explizit mit selbst programmierten Befehlen oder implizit mit asynchronen Aufrufen.--
Viele Gruesse
Peter- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 30. Oktober 2012 12:11
Alle Antworten
-
Hi xPhil,Thread.Sleep mit 1 ms ist keine gute Lösung, da die CPU sehr intensiv belastet wird. Besser ist es z.B. ein AutoResetEvent zu nutzen, welches in der DataReceivedHandler-Methode gesetzt wird, wenn alle Daten angekommen sind. Auf die Auslösung des AutResetEvent kann gewartet werden. Wie das Warten am besten implementiert wird, hängt vom Gesamtkonzept ab. Der Aufrufer arbeitet entweder synchron, asynchron oder mit Ereignisroutine (Endeereignis). Bei synchroner Arbeitsweise wartet die die aufgerufene Methode auf das AutoResetEvent. Bei asynchroner Arbeitsweise wird gestartet und ein Callback mitgegeben, welches für den Aufruf bei Übertragungsende genutzt wird. Für eine Ereignisauslösung ist die Nutzung des SerialPort zu kapseln und das Endeereignis wird entweder in der DataReceivedHandler-Methode ausgelöst oder ein Warten auf das AutoResetEvent löst das Endeereignis aus. In jedem Fall ist mit multithreading zu arbeiten, entweder explizit mit selbst programmierten Befehlen oder implizit mit asynchronen Aufrufen.--
Viele Gruesse
Peter- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 30. Oktober 2012 12:11
-
Hallo xPhil Johnson,
Ich gehe davon aus, dass die Antwort Dir weitergeholfen hat.
Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.Grüße,
RobertRobert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.