Hallo Leute,
ich habe ein Problem mit einem Programm das ich zurzeit schreibe. Das
Programm soll Befehle über die serielle Schnittstelle an ein externes,
von mir gebautes Messgerät senden sowie Messwerte empfangen. Ersteres
klappt ohne Probleme. Der zweite Teil macht allerdings Probleme. Zur
Ansteuerung der seriellen Schnittstelle nutze ich den folgenden Code:
http://www.tetraedre.com/advanced/serial2.php
Zum Programmieren des Steuerungsprogrammes nutze ich Borland C++ 6.
Ich werde einmal kurz die Verfahrensweise erläutern nach der ich
vorgehe.
Jedes mal wenn ein Ereignis der seriellen Schnittstelle eintritt wird
die nachfolgende Funktion aufgerufen (SERIAL_DATA_ARRIVAL ist hier
wichtig), das ganze läuft intern wohl thread-basiert (Serial2 von
Tetraedre):
Wenn ich also ein Zeichen empfange, schreibe ich dass in einen
Ringbuffer und Rufe eine Funktion auf die div. Felder neu besetzt, bzw.
die Daten solange über die serielle Schnittstelle einließt bis ein
Telegramm beendet ist (\n).
Die Funktion sieht wie folgt aus:
Darin mache ich ziemlich viele Sachen wie z.B. einen Graphen mit den
emfangenen Messwerten zu zeichnen. Weiterhin schreibe ich die Rohwerte
die ich über die serielle Schnittstelle empfange in ein Memo (
MainForm->RawMemo->Lines->Add(recvMsg);).
Jetzt zum eigentlichen Problem: Wenn ich die Zeile:
MainForm->RawMemo->Lines->Add(recvMsg);
auskommientiere klappt alles ohne Probleme, sobald ich diese drin habe
bekomme ich bei beenden die Fehlermeldung "Code 1400: Ungültiges
Fensterhandle". Hinzuzufügen ist, dass ich auch in die Memo schreibe
wenn diese nicht im Fokus ist....
Ich denke das Problem wird sein, dass ich in einem Thread auf die Memo
schreibe während diese schon zerstört wurde, oder das es ein Problem ist
das ich darauf schreibe wenn diese nicht im Focus ist.
Vllt. könnt ihr mir da einen Tipp geben...
Patrick L. schrieb:> MainForm->RawMemo->Lines->Add(recvMsg);> auskommientiere klappt alles ohne Probleme, sobald ich diese drin habe> bekomme ich bei beenden die Fehlermeldung "Code 1400: Ungültiges> Fensterhandle"
Du kannst nicht aus einem beliebigen Thread heraus auf Objekte des
GUI-Threads zugreifen.
Wie finde ich den heraus in welchen Thread updateForms(); ausgeführt
wird?
Ich hab angenommen, dass das im Kontext des MainThread aufgerufen wird.
Wenn das nicht der Fall ist, wie würdest du das lösen?
Ich finde die Lösung wie ich sie im Moment habe auch nicht gerade
elegant, vorallem wie wird sichergestellt, dass die Verarbeitung des
empfangenen Telegrammes beendet ist bevor ein neues eintrifft?
Von der Messgerät-Seite sende ich mit 115200 Baud einen Burst von
Messwerten (ca. 40 Zeichen) alle 100ms.
Was mir noch aufgefallen ist, wenn ich
1
MainForm->RawMemo->Lines->Add(recvMsg);
nur durchführe wenn der Reiter für die Rohwerte aktiv ist (also somit im
Fokus), also so:
Was mich auch noch wundert ist, dass das füllen des Graphen scheinbar
keine Probleme verursacht:
MainForm->Series1->AddXY(...)
Das hinzufügen der Messwerte zu einer MemoBox
MainForm->RawMemo->Lines->Add
allerdings schon, wie auch schon oben beschrieben.
Hi,
um auf GUI Elemente zu schreiben gibt es eine Sync-Funktion!
Ich hab mal meine alten Links durchsucht und diesen noch gefunden:
http://bcb-tutorial.c-plusplus.de/Thread/artikel5.html
vielleicht hilft dir das.
>Von der Messgerät-Seite sende ich mit 115200 Baud einen Burst von>Messwerten (ca. 40 Zeichen) alle 100ms.
Das wird sehr schwierig, die 100ms sind zu klein!
Je nach dem PC und den Programmen die ausgeführt werden kann es sein das
ein Programm mal nicht ran kommt!
Aber Du hast ja zum Glück einen End-Kenner im Telegramm, vielleicht
reicht das ja doch.
Aus meinen Erfahrungen sollten es min 500ms sein oder besser
>1000ms.(bei Burst-Betrieb)
Die bessere Lösung für den PC ist es wenn er die Daten abfragen kann, so
kommt er nicht durch einander.(1 Abfrage -> 1 Antwort)
Stephan schrieb:> Hi,> um auf GUI Elemente zu schreiben gibt es eine Sync-Funktion!> Ich hab mal meine alten Links durchsucht und diesen noch gefunden:>> http://bcb-tutorial.c-plusplus.de/Thread/artikel5.html>> vielleicht hilft dir das.
Danke für den Link, diesen hatte ich auch schon gefunden und auch
ausprobiert. Dabei ist mir dann aufgefallen, dass Daten z.B. der MemoBox
hinzugefügt werden (Zu erkennen daran, das die Scrollbar kleiner wurde)
aber diese nicht angezeigt wurden.
Stephan schrieb:> Das wird sehr schwierig, die 100ms sind zu klein!> Je nach dem PC und den Programmen die ausgeführt werden kann es sein das> ein Programm mal nicht ran kommt!> Aber Du hast ja zum Glück einen End-Kenner im Telegramm, vielleicht> reicht das ja doch.> Aus meinen Erfahrungen sollten es min 500ms sein oder besser
Kann ich leider nicht verlängern. Außerdem kommen ja Terminal Programme
wie HTerm auch damit klar.
>dass Daten z.B. der MemoBox>hinzugefügt werden (Zu erkennen daran, das die Scrollbar kleiner wurde)>aber diese nicht angezeigt wurden.
Ja das kenne ich so auch.
Es liegt daran das das Memo nicht neu gezeichnet wird(ist länger her)
Zum Testen einfach mal 'Application->Process....' aufrufen(Hab den Namen
vergessen), oder das Memo einen 'Refresh' oder 'Update' ausführen
lassen.
Ist schon länger her als ich mit BC++6 gearbeitet habe.
>Kann ich leider nicht verlängern. Außerdem kommen ja Terminal Programme>wie HTerm auch damit klar.
Ja, das kenne ich auch. :-[
Ich weiß bis heute nicht warum der Laptop vom Chef damals nicht unter 1
sec Timeout gearbeitet hat!!! (war ein älterer Celeron Laptop mit XP)
Mir sind dort die Events verloren gegangen.
Probier es aus, vielleicht gehts bei dir gut. Mit meinem PC damals hat
es ja auch geklappt. :-)
Aber bei einigen Kunden (alte PCs) und der Laptop vom Chef wollten damit
nicht laufen.
Bei XP war der Taskwechsel doch bei 10ms oder so. Wie siehts denn bei
heutigen Win Versionen aus?
Stephan schrieb:> Hi,> um auf GUI Elemente zu schreiben gibt es eine Sync-Funktion!> Ich hab mal meine alten Links durchsucht und diesen noch gefunden:>> http://bcb-tutorial.c-plusplus.de/Thread/artikel5.html>> vielleicht hilft dir das.
Ich habe das Beispiel nochmal komplett von vorne durchprobiert, ich
hatte bei meiner vorherigen Implementierung einen Fehler eingebaut.
Jetzt scheint auch eine Ausgabe zu funktionieren, danke..
Noch eins,
bei der RS232 API gabs bei mir mal so ein Event-Char, damit kann man die
'Eventlast' im System minimieren. (anstatt bei jedem Byte ein Event
auszulösen)
Aber dies nur als Hinweis!!!!
Ja, das Problem lag wohl tatsächlich daran, dass updateForms(); aus dem
Kontext des "serielle Daten" Thread aufgerufen worden ist. Da wurde auf
VCL Komponenten, die dann immer sporadisch Exceptions verursacht haben
(List index out of Bounds, Ungültiges Fensterhandle, ...).
Jetzt habe ich das ganz so wie in dem Beispiellink getrennt.
Die Daten werden in einen Ringbuffer geschrieben, sobald das Ende
erkannt wird wird ein Thread geöffnet der über Synchronize die Daten
aufteilt und die entsprechenden Felder, EditBoxen, Graphen, Memos,
etc... besetzt.
Ist das vollendet wird der Thread beendet, "parallel" werden natürlich
schon wieder neue Daten in den Ringbuffer geschrieben.