Zugriff auf Daten durch verschiedene Threads

Hallo!

Ich habe folgende Problemstellung: Eine über einen virtuellen, seriellen COM-Port wird ein Programm mit Daten versorgt. Die kommen recht häufig (ca. alle 10ms) mit einer Baudrate von 128kBaud. Jedes Byte löst ein Event aus, liest das Datum und speichert es in ein Array.
In größeren Abständen (alle 100ms) werden die Daten grafisch in ein Fenster gezeichnet. Das kann man sich wie das Bild eines Oszilloskops vorstellen. Die Funktion, die das Bild des Fensters zeichnet, greift auf dasselbe Array zu, in das aus der Klasse für die serielle Schnittstelle geschrieben wird.
Das Programm läuft momentan unter Java recht zufriedenstellend. Die serielle Kommunikation und die Klasse für das Grafikfenster laufen in verschiedenen Threads.

Nun zu meiner Frage:
Ich möchte das Programm in C++ schreiben und nutze dafür die VC++ Express Edition. Dort gibt es die Klasse SerialPort und ich möchte eine einfache Windows-Forms Anwendung erstellen, die im Prinzip dasselbe macht wie das bereits existierende Java-Programm.

Ich würde gern erfahren, wie eure Erfahrungen mit einer solchen Problemstellung sind. Mit welchem Konzept würdet ihr dies in C++ umsetzen, insbesondere das Handling der Daten? Worauf muss ich besonders achten, wenn ich Daten, die in einem Thread erzeugt werden, in einer GUI zeichnen möchte, ohne dass es zu Problemen kommt (verschluckte Zeichen, zu langsame Datenübertragung usw…)?
Ich frage deshalb, weil ich bisher in erster Linie mit Java beschäftigt war, und die Besonderheiten bei so etwas in C++ nicht gut genug kenne.
Wie man generell mit der Klasse SerialPort umgeht ist mir bekannt, aber bekanntlich gibt es ja viele Wege nach Rom, manche sind nur etwas steiniger als andere (wenn man nicht den richtigen kennt)…

Was hättet ihr für Ideen, wie man dies geschickt umsetzen könnte?

Vielen Dank im Voraus für eure Antworten!

Gruß

Michael

Ich weiß jetzt nicht genau, ob ich dein Problem vollständig erfasst habe. Aber aus programmiertechnischer Sicht ist das doch ein Consumer-Producer-Problem?

D.h. ein (oder der) interessante Aspekt ist, wie man es schafft, dass sich die beiden Threads (A holt die Daten von der Seriellen, B visualiert) nicht in die Quere kommen. Das ist ein Standardproblem, so wie Sortieren, etc. Ein Ringbuffer zwischen den beiden und eine thread-safe Implementierung fürs Daten Reinstecken (macht A) und Rausholen (macht B) muss dann gemacht werden; oder es gibt das schon.

Die Idee ist jedenfalls, dass der Buffer A und B von einander trennt. Und die Aufgabe von B ist dann trivial: Hole wieder xx Bytes vom Buffer und visualisiere diese. Dann musst du dir nur überlegen, wie groß der Buffer sein soll. Vielleicht einfach mal doppelt so groß, wie B in einem Durchgang holt…

mfg.

[1] http://en.wikipedia.org/wiki/Producer-consumer_problem

Hallo!

Vielen Dank erstmal für deine Antwort!

Ich weiß jetzt nicht genau, ob ich dein Problem vollständig
erfasst habe. Aber aus programmiertechnischer Sicht ist das
doch ein Consumer-Producer-Problem?

Genau das ist es (zumindest erinnere ich mich dunkel daran aus einer Vorlesung). Die Grundproblematik dabei ist mir soweit klar, aber:

D.h. ein (oder der) interessante Aspekt ist, wie man es
schafft, dass sich die beiden Threads (A holt die Daten von
der Seriellen, B visualiert) nicht in die Quere kommen. Das
ist ein Standardproblem, so wie Sortieren, etc. Ein Ringbuffer
zwischen den beiden und eine thread-safe Implementierung fürs
Daten Reinstecken (macht A) und Rausholen (macht B) muss dann
gemacht werden; oder es gibt das schon.

Genau so eine Antwort suchte ich (fast :smile:. Die Frage, die ich mir stelle ist, werden solche Mechanismen durch C++ unterstützt, und wenn ja, wie?
Ich will eben gerade verhindern, mir im Code ein Bein auszureißen (eben der steinige Weg), wenn es in der Sprache schon elegante Konstrukte für eben ein solches Standardproblem gibt. Da ich aber kein Informatiker bin, schüttel ich das nicht mal so eben aus dem Ärmel und weiß auch nicht, welche Klassen und Methoden hierfür hilfreich sind.

Die Idee ist jedenfalls, dass der Buffer A und B von einander
trennt. Und die Aufgabe von B ist dann trivial: Hole wieder xx
Bytes vom Buffer und visualisiere diese. Dann musst du dir nur
überlegen, wie groß der Buffer sein soll. Vielleicht einfach
mal doppelt so groß, wie B in einem Durchgang holt…

Ok, verstanden… Soweit ich weiß, läuft SerialPort in einem eigenen Thread. Ich würde versuchen, die ankommenden Daten in ein Array zu schreiben, das ich in die Klasse SerialPort einfüge.
Wo ich jetzt nicht weiterkomme ist, was muss ich tun, damit die Daten aus diesem Array in einen Buffer gelangen, der sich beispielsweise in einem anderen Thread (etwa einem GUI-Thread, der den Graph zeichnet) befindet. Wie bekomme ich das thread-sicher hin, ohne das der Datenempfang über die serielle Schnittstelle beeinträchtigt wird?

Gruß

Michael

Servus,

also die Sprache C++ per se bietet keine Sprachkonstrukte im Zusammenhang von concurrent programming. Allerdings gibt es Libraries, die dir das Coden von solchen Code (teilweise oder völlig) ersparen. Als Beispiel kann z.B. die unter C++ Programmierern wohl gut bekannte Boost Library dienen.

Siehe etwa: http://www.boost.org/doc/libs/1_35_0/libs/circular_b…. Es ist vielleicht eine gute Sache, wenn du dir das Konzept von diesem Ringbuffer mal durchliest.

Es sei allerdings drauf hingewiesen, dass dieser Ringpuffer nicht thread-safe ist. Unter http://www.boost.org/doc/libs/1_35_0/libs/circular_b… findet man thread-safe Code diesbezüglich.

Allerdings kann ich nur betonen: Solltest du mit concurrent programming in berührung kommen, dann würde ich wärmstens empfehlen, dich mit dieser Problematik auseinander zu setzen. Es können daraus Bugs entstehen, die extrem (!) hart zu finden sind: Fehler, die nur einmal in 1000 Fällen auftreten und das scheinbar völlig zufällig. Man sei gewarnt…

Viel Spass beim C++en.

1 Like

Vielen Dank für deine Hilfe! Dann habe ich jetzt wohl erstmal ein wenig zutun :smile:

Gruß

Michael