Hallo zusammen, ich brauch mal eure Hilfe. Ich habe eine DLL mit C++ erstellt, in der sich diverse Routinen für die RS232 befinden (z.B. send_data(), receive_data(), setup_comm() usw.). Von einem anderen Programm binde ich die DLL ein, bzw. nutze die Funktionen innerhalb der DLL. Alle Funktionen liefern hierbei ein Ergebnis zurück - meist eine BOOL (z.B. success = receive_data(Parameter)). Da ich innerhalb der Funktion receive_data im Polling-Modus auf Daten warte, und gleichzeitig dort auch einen Timeout-Timer laufen habe, kommt es nun vor, dass der Timeout-Timer (ca. 3s) immer dann anspricht, wenn keine Daten über die RS232 von einem entsprechenden Device zurückkommen - soweit ist das ja OK. Aber jetzt ist es so, dass mein Hauptprogramm ca. 70 Devices, die über einen Bus vernetzt sind, in regelmäßigen Abständen abfragt (abfragen muss!) Da es sich um eine Art TOKEN-RING-BUS handelt (HARDWARE ist fest vorhanden und NICHT verhandelbar!) kann es in seltenen Ausnahmen vorkommen, dass eben ein Device in dieser Kette nicht mehr reagiert und somit das Gesamtsystem lahmlegt. Dann spricht bei jeder Abfrage der Timeout-Timer an - bei 70 Devices a)3s kann man sich ja ausrechnen, wie lange das Gesamtsystem blockiert wird. Soviel zum Vorgeplänkel. Jetzt meine Frage: Welche Möglichkeit habe ich, dass z.B. die Daten nicht mehr im Polling-Modus abgefragt werden? Wie kann ich, solange noch kein Rückgabewert der Funktion vorhanden ist, im Hauptprogramm weitermachen, ohne dass das System blockiert wird. Als Parameter zum Aufruf der Funktion dient u.a. ein Pufferbereich, der die Daten aufnehmen soll, die Adresse des abzufragenden Devices usw. Danke schon mal - auch fürs durchlesen Gruß TK
Hi In deinem Fall wäre es günstiger der COM-Schnittstelle einen eigenen Thread zu spendieren. Die Kommunikation zwischen Hauptprogamm und Thread erfolgt dann nur noch auf der Message-Ebene. Wenn du wissen willst, wie so etwas aussieht, dann suche mal nach 'cport'. Version 3 oder höher. MfG Spess
Das mit einem eigenen Thread ist so eine Sache. Ich benutze die DLL mit den 'Low-Level-Routinen' in fast allen Programmen, die eine RS232 Kommunikation benötigen. Da müsste ich ja alle Programme umschreiben. Ist dann doch ein wenig zu viel. Ich komme um die DLL nicht herum. Mein erster Lösungsansatz war eigentlich die Timeout-Zeit von 3s auf z.B. 300ms zu reduzieren. Die Frage ist dann nur, ob die Devices nicht doch gerade in einer Interruptroutine irgendwas machen (z.B. Zeit verbraten). Wie könnte ich denn innerhalb der DLL einen Thread aktivieren, der die Daten von der RS232 einliest UND wie kann ich dann dem Hauptprogramm mitteilen, dass die Daten im Puffer stehen, wenn die DLL-Funktion bereits verlassen wurde? Das ist hierbei mein größtes Problem. Kurz gesagt - ans Hauptprogramm möchte ich nicht ran. Aber wahrscheinlich komm ich wohl nicht darum. Gruß TK
Hi Vorab erst mal : ich programmiere meine Programme mit Delphi. Aber die Verwendung von API-Funktionen verläuft genauso wie unter C++. Hast du die die Routinen in eine eigene Class verpackt? Wenn nicht, gehst du am Konzept von C++ vorbei und da sind deine Schwierigkeiten vorprogrammiert. MfG Spess
Ich habe die Routinen nicht in eine Klasse verpackt. Ich sehe aber hier auch nicht das Problem. OK - nur weil ich den Borland C++ Compiler hab muss ich ja nicht unbedingt immer auf die C++ Konzepte zurückgreifen. Im übrigen versteht der ja auch Delphi. Wo wäre denn der Vorteil bei der Behebung meines Problems, wenn die Routinen in einer Klasse stecken würden? Gruß TK
Hi Wie gesagt, ich komme aus der Delphi-Ecke. Der Vorteil für mich ist, dass ich eine Serielle Schnittstelle als Komponente in ein Formular einfügen kann. Über die Schnittstellen der Komponente wird dann auf die Eigenschaften und Funktionen zugegriffen. Zum Beispiel kann deine Komponente(class) einen eigenen Timer besitzen. Der fragt in bestimmten Abständen den COM-Port ab und liest ,wenn vorhanden, die Daten in einen internen Puffer. Danach wird eine Nachricht (message) an das Hauptprogramm geschickt. Das Hauptprogramm holt dann die Daten über eine Funktion der Class ab. Damit hast du die eigentliche Behandlung des COM-Ports vom Hauptprogramm abgekoppelt. Dein Hauptprogramm kann dann in aller Ruhe überprüfen, ob irgendwelche Sender ein Timeout haben, ohne blockiert zu werden. MfG Spess
Generell hab ich auch kein Problem mit Delphi. Ich hab AUCH in C++ eine Komponente für die serielle Schnittstelle. Die kann ich hier aber nicht benutzen (Lizenzprobleme)! Deshalb hab ich ja die DLL geschrieben. Die kann ich nämlich weitergeben, OHNE Probleme mit anderen zu bekommen. Und selbst eine Komponente erstellen - so weit bin ich noch nicht in die Materie eingestiegen. Klar hat eine Komponente die Vorteile, die du angesprochen hast. Man kann dann schön auf Ereignisse reagieren usw. Nur ist es bei diesem Projekt so, dass ich zwar das Hauptprogramm erstellt habe, aber dieses nur als "Demo" an einen Kunden rausging. Der hat jetzt sein eigenes Programm entwickelt und muss eben die DLL für die Kommunikation mit den Devices benutzen (da sind eben nicht nur RS232 Routinen drin). Da liegt jetzt das Problem. Ich bzw. er kommt ohne die DLL nicht klar. Und die Routinen/Funktionen offen legen möchte ich dann auch nicht. Vielleicht gibts ja eine Möglichkeit einen GLOBALEN Puffer zu deklarieren, den sowohl das Hauptprogramm, als auch die DLL benutzen können. Den könnte man ja dann füllen, wenn tatsächlich Daten da sind. Demnach müsste jede DLL Routine sofort wieder verlassen werden und das Hauptprogramm müsste dann zyklisch den Inhalt des Puffers prüfen. Aber auch hier seh ich eigentlich zu viel Aufwand für die DLL und das Hauptprogramm. Momentan bin ich echt ratlos. Gruß TK
Hallo, nur damit ich es verstanden habe: - ca. 70 Geräte hängen am gleichen CommPort - Dein Hauptprogramm ruft eine Funktion in der DLL auf um Daten an ein einzelnes Gerät zu senden oder von einem einzelnen Gerät zu empfangen. Unter dieser Annahme, könntest Du in der DLL einen Thread bauen der von sich aus mit allen Geräten spricht und die Ergebnisse in ein einen Puffer ablegt. Deine Funktionen die von Deinem Hauptprogramm aufgerufen werden lesen dann z.B. nicht mehr von der Schnittstelle sondern aus der Ergebnisliste. Da da z.B. drinnsteht, das ein Timeout aufgetreten ist muss der Funktionsaufruf nicht bis zum Timeout dauern, sondern kehrt sofort zurück. Allerdings musst Du mit Threads in DLLs aufpassen. Z.B. darfst Du im Initialisierungsbereich keine Threads erzeugen oder im Zerstörungsbereich keine Threads beenden. Falls Dein Hauptprogramm eine Funktion "Öffen CommPort" aufruft kannst Du dort den Thread erzeugen (und bei "Schließe CommPort" beenden). Und du musst den Zugriff auf Deine Ergebnisse mit z.B. Critical Sections schützen, damit nicht das Chaos losbricht wenn Dein Hauptprogramm und Dein Thread gleichzeitig auf diese Bereiche zugreifen. Gruß Ekkehard
@ Ekkehard Genau so / so ähnlich hab ich mir das vorgestellt. Jetzt mal zu meinem Verständnis: Also die DLL agiert autark und fragt dann zyklisch alle Teilnehmer von sich aus ab, trägt die gesammelten Daten in einen Ereignispuffer und wartet nur noch darauf, dass das Hauptprogramm den Puffer ausliest. OK - soweit verstanden. Jetzt kommt allerdings eine Kleinigkeit dazu. Es gibt ja mehrere Funktionen innerhalb der DLL, die auch unterschiedliche Ereignisse an den Devices auslösen. Also z.B. Datenwerte abfragen, Parameter übergeben, Selbsttests durchführen lassen usw. Und jede dieser Routinen benutzt letztendlich die Schnittstelle mit den Timeoutvorgaben. Durch den Thread könnte ich also z.B. die Hauptfunktion (nämlich Datenwerte abfragen) automatisieren. Alle anderen Funktionen würden ohne Threadsteuerung arbeiten wie bisher - also mit Timeout. Aber ich denke, das wäre schon mal ein riesiger Schritt in die richtige Richtung. Ich mach mich dann mal an die Überlegungen für einen Threadaufbau und dann an die Programmierung. Danke erst mal Gruß TK
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.