Hallo, ich habe folgendes Problem. Ich schreibe gerade an einer Anwendung die am Ende mit einem extern angeschlossen Gerät (FTDI USB-Seriell) Daten austauschen soll. Aktueller Stand ist, dass ich erkennen kann, wenn das Gerät angeschlossen oder abgezogen wird und an welchem Port. Das würde ich gern beibehalten. Die Kommunikation läuft so, dass ich ein Kommando sende und das Gerät entsprechend antwortet und da liegt mein Problem. Die Daten können auch schon mal ein paar KByte sein. Ich bin aber bestrebt, den Serial Port nur zu öffnen, wenn es sein muss und ihn nach dem Senden wieder zu schließen, damit ein Abziehen des Gerätes nicht zu undefinierten Zuständen führt. Deshalb weiß ich nicht so recht, wie ich die Kommunikation strukturien soll. Variante 1: Kommando senden, warten, lesen, Port schließen. Variante 2: Kommando senden, Port offen lassen, auf DatenEvent reagieren, dort lesen und Port schließen. Variante 2 gefällt mir besser, hat aber Unwegbarkeiten. Weil, wenn nix kommt, bleibt der Port offen, was Mist ist. Danke im Voraus für eure Anregungen. Grüße, Alex
:
Bearbeitet durch User
Alexander H. schrieb: > Variante 1: Kommando senden, warten, lesen, Port schließen. würde ich verwenden. Das ganze aber in einem eigenen Thread - damit die GUI nicht blockiert. Ein das Readtimeout sollte man setzen, damit das lesen nicht ewig blockiert. > Variante 2: Kommando senden, Port offen lassen, auf DatenEvent > reagieren, dort lesen und Port schließen. hier kommt noch dazu das du im schlimmsten fall jedes Byte einzeln bekommst. Du musst also sammeln.
Hallo Peter, danke für deinen Post. Serial Port läuft eh in einem eigenen Thread, soweit ich weiß. Wie ist das mit dem ReadTimeout, gilt das auch für ReadExisting oder nur für ReadTo(string)? Grüße, Alex
Alexander H. schrieb: > danke für deinen Post. Serial Port läuft eh in einem eigenen Thread, > soweit ich weiß. nein nicht zwingend. > Wie ist das mit dem ReadTimeout, gilt das auch für > ReadExisting oder nur für ReadTo(string)? ReadExisting macht bei direkten lesen (ohne Event) keinen sinn. Ich würde nur mir Read arbeiten. was für Daten bekommst du? woher kennst du die Länge?
Die Daten sind Strings als Command Response und Binärdaten die bei einer Messung entstanden sind. Da ich die Datenrate und die Messzeit etwa kenne, kann ich abschätzen, was zusammenkommt, das kann aber variieren. Ich müsste also vorher die Länge senden, damit Read weiß, was kommt, oder? Ich will nicht streiten, aber ich dachte SerialPort port = new SerialPort(); instanziiert einen Port in einem eigenen Thread. Korrigiere mich bitte, wenn ich da falsch liege. Wenn ich solche Daten dartstellen wollte, ging das nur über Invoke oder es gab 'ne Cross-Thread-Exception.
:
Bearbeitet durch User
Alexander H. schrieb: > Ich will nicht streiten, aber ich dachte > > SerialPort port = new SerialPort(); > > instanziiert einen Port in einem eigenen Thread. meines wissens nicht http://msdn.microsoft.com/de-de/library/system.io.ports.serialport.datareceived(v=vs.110).aspx > Das DataReceived-Ereignis wird in einem sekundären Thread ausgelöst ich denke nicht das für jeden com-port ein extra Thread geöffnet wird. Es wird wohl ein "globalen" sekundären Thread geben der die Schnittstelle mit WaitForMultipleObjekts überwacht.
Ich fahr mal heim und meld mich dann nochmal. Danke erstmal.
Was soll es denn bringen den Port immer wieder zu oeffnen und zu schliessen? Es genuegt den Port bei Beenden zu schliessen. Sonst soll ja eh keine Applikation mit dem Device reden koennen. Eine solche Kommunikation sollte man eh zustandslos machen. Dh das device muss verschwinden koennen und wieder kommen, ohne was zu blockieren. Daher sollte man die Kommunikation auch nicht blockierend machen. Weshalb und woher sollten undefinierte Zustaende resultieren?
Bei SerialPort.Open() wird intern ein SerialStream-Objekt erzeugt, welches via CreateFile() den COM-Port öffnet, ein paar Einstellungen setzt und dann einen (Hintergrund-)Thread startet (pro Objekt, nicht global für die SerialPort-Klasse) Im Thread wird praktisch in Schleife WaitCommEvent() aufgerufen. Sollte ein Event aufgetreten sein, ruft es ThreadPool.QueueUserWorkItem(..) auf worin wiederrum das entsprechende Event gefeuert wird ;D D.h. wenn man z.B. im DataReceived-Event ist, hat die SerialPort-Klasse sogar 2 Threads am Laufen (den WaitCommEvent-Event Thread und den DataReceived-Thread aus dem ThreadPool ;D) (so sieht es zumindest mit ILSpy für .net 4.0 aus) --- wenn man einfach SerialPort.Read() aufruft und die Events (DataReceived, etc.) nicht nutzt, hat man von diesen Threads natürlich nichts ;D
@!!Troll Alarm!! Das Problem tritt auf, wenn man bei geöffnetem Port einfach das Gerät abzieht und damit der COM-Port nicht mehr existiert. Ich muss nochmal suchen, wo's stand, ich hatte aber gelesen, dass das nicht gut ist, weil im Hintergrund Sachen passieren, die nicht bis zu Applikation durchkommen. Hatte irgendwas mit dem Stream zu tun. Kannst Du mir bitte näher eklären, was du mit zustandslos meinst? Grüße, Alex
Salut, ich hab nochmal recherchiert. 1. Wenn ich das richtig verstanden habe, ist meine Kommunikation schon zustandlos, weil der Server (das Gerät) sich keine Zustände merkt, sondern bei der Anfrage alle Informationen mitgesendet bekommt. 2. Ich bin dabei, die Kommunikation wie folgt zu implementieren: Der Port bleibt jetzt immer geöffnet. Das Problem mit der Undefiniertheit habe ich hoffentlich gelöst. Ich verwende jetzt das DataReceivedEvent. Es gibt einen Timer für ein timeout, anhand dessen ich detektieren kann, wenn mitten in der Kommunikation was schief läuft und der bei jedem Empfang rückgesetzt wird. Weiterhin habe ich eine enum Valiable definiert, die mir den Zustand der Kommunikation liefert und anhand der dann die empfangenen Daten behandelt werden. Ich würde euch nochmal um Verbesserungen und Anregungen bitten. Grüße, Alex
:
Bearbeitet durch User
Moin, das ist doch Kindergarten, mach doch erstmal und frag dann. Die Daten von deinem Messgerät werden bestimmt auch terminiert gesendet (CR/LF), also ein readline und danach die daten verarbeiten...wo ist das Problem? Gruß Jonas
Auch wenn deine Antwort recht unfreundlich rüberkommt: (CR/LF) war der entscheidende Hinweis. Ich hatte nähmlich ein anderes Terminierungszeichen verwendet, was aber eigentlich nicht sehr clever war. Danke. PS.: Heute ist Freitag, kein Grund, mürrisch zu sein.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.