Wie führe ich einen nicht blockierenden Lesen über asio?
Ich bin versucht, die Verwendung von boost::asio Lesen und schreiben von einem Gerät über eine serielle Schnittstelle. Beide boost::asio:: Lesen() und boost::asio::serial_port::read_some () - block, wenn es nichts zu Lesen. Stattdessen würde ich gerne um diesen Zustand zu erkennen und schreiben Sie einen Befehl, um den port zu " kick-starten Sie das Gerät.
Wie kann ich entweder erkennen, dass keine Daten verfügbar sind?
Falls nötig, kann ich alles tun, asynchron, nur würde ich eher vermeiden, die zusätzliche Komplexität, wenn ich kann.
InformationsquelleAutor Joe Ludwig | 2009-01-18
Du musst angemeldet sein, um einen Kommentar abzugeben.
Haben Sie ein paar Optionen, eigentlich. Sie können entweder den seriellen port integrierte
async_read_some
- Funktion, oder verwenden Sie die stand-alone-Funktionboost::asio::async_read
(oderasync_read_some
).Du wirst immer in die situation, wo Sie sind gewissermaßen "blockiert", da keiner von diesen rufen die callback-es sei denn, (1) Daten, die gelesen worden ist oder (2) ein Fehler Auftritt. Um dies zu umgehen, werden Sie wollen, zu einem
deadline_timer
Gegenstand, um ein timeout. Wenn der timeout feuert zuerst, keine Daten verfügbar. Andernfalls müssen Sie die Daten Lesen.Die zusätzliche Komplexität ist nicht wirklich schlecht. Sie werden am Ende mit zwei Rückrufe mit ähnlichen Verhalten. Wenn entweder "Lesen" oder "timeout" callback feuert mit einem Fehler, wissen Sie, es ist das Rennen der Verlierer. Wenn man entweder feuert ohne Fehler, dann wissen Sie, es ist der Gewinner des Rennens (und sollten Sie Abbrechen, die anderen nennen). In dem Ort, wo Sie hätte Ihre blockierenden Aufruf zu
read_some
Sie haben nun einen Aufrufio_svc.run()
. Ihre Funktion wird immer noch blockiert nach wie vor, wenn er fordertrun
, aber dieses mal Steuern Sie die Dauer.Hier ein Beispiel:
Dass sollte Ihnen den Einstieg mit nur ein paar tweaks hier und da an Ihre speziellen Bedürfnisse anpassen. Ich hoffe, das hilft!
Noch ein Hinweis: es gibt Keine zusätzlichen threads notwendig waren, Rückrufe zu handhaben. Alles geschieht im Aufruf
run()
. Nicht sicher, ob du schon bewusst...ich hatte anscheinend zu rufen io_svc.reset() nach io_svc.run().
tolle Antwort, sehr nützlich. Allerdings bin ich immer ein seltsames Verhalten: ich habe ein Programm schreiben der Daten auf die serielle Schnittstelle alle 5 ms und andere Lektüre fromit, jedoch wenn ich den async-Verzögerung auf 5 ms auf den Leser Teil, ich bekomme immer noch einige "Daten nicht verfügbar", ruft gemischt mit dem Lesen von Werten. Ist dies verursacht durch ein overhead an code, oder bin ich etwas fehlt?
(Späte Antwort, aber seit ich hier bin, kann ich auch beantworten...) @joaocandre, wenn eine Verspätung ist genau das gleiche wie Ihr schreiben-Frequenz, ist es durchaus möglich, dass das schreiben in Verzug, sehr leicht und Ihre lese-thread wartet, die Zeit passt genau zwischen zwei schreibversuche Timer theoretisch präzise, aber deine threads werden in sync-und Zeitplanung wird wahrscheinlich geben Sie das unerwünschte Ergebnis 50% der Zeit. Ich würde empfehlen, eine längere Verzögerung auf der Seite Lesen (z.B. 50% länger).
InformationsquelleAutor Brian
Haben Sie mit dem gratis-Funktion asio::async_read.
InformationsquelleAutor
Seine eigentlich viel einfacher als die Antworten, die Sie hier angedeutet haben, und Sie können es synchron:
Angenommen, Ihre Blockierung zu Lesen, war etwas wie:
Dann ersetzen Sie es mit
Verwenden Sie die alternative überlastet form von receive_from, die fast alle die send/receive-Methoden haben. Leider nehmen flags-argument, aber 0 scheint gut zu funktionieren.
InformationsquelleAutor S.N.