TIdTelnet->OnWorkEnd
-
Hallo,
neuer Tag, neues Problem...
Vorgeschichte: Ich habe in meinem Prog einen 2. Thread, in dem Daten empfangen werden. Wenn der Empfang einer Datenmenge abgeschlossen ist, soll der 2. Thread die Daten an den Hauptthread übergeben und dort eine Verarbeitungsroutine starten. Vom 2. Thread aus die Verarbeitung (Routine) im Hauptthread zu starten funktioniert bereits, auch die Übergabe der Daten. Nur leider nicht zum richtigen Zeitpunkt!
Das Problem: Ich nutze für die Verbindung und die Datenübertragung die IndyKomponente TIdTelnet. Dort gibt es ein Ereignis "OnWorkEnd". Nun dachte ich, dieses Event lässt sich dazu nutzen festzustellen, wann eine Datenmenge vollständig übertragen wurde. Also gleich mal in die Hilfe geschaut: Suchbegriff: TIdTelnet. Danach in der Tabelle auf OnWorkEnd geklickt. Und dann Verständnisprobleme:
OnWorkEnd is ... signalled when completing a read or write operation on the connection.
Liest sich für mich so: OnWorkEnd ... wird angezeigt, wenn Lese- oder Schreibvorgänge auf der Verbindung abgeschlossen sind.
(1) Ist das so richtig verstanden / wiedergegeben und wenn nicht, wie ist es dann eventuell gemeint?
Wenn es so richtig ist, könnte ich das ja abfragen mit "if" und dann die Verarbeitung starten. Stellt sich dann für mich nur folgende Frage:
(2) Wie / welchen Wert kann ich abfragen?
Mit:
if (...->OnWorkEnd == true)funktionierts zB. nicht. Fehlermeldung:
[C++ Fehler] Unit1_RxDThread.cpp(39): E2034 Konvertierung von 'int' nach 'TWorkEndEvent' nicht möglich(3) Wo arbeite ich denn in der Abfrage mit int???

Kann mir jemand einen kleinen Schritt weiterhelfen?
MfG
-
Hallo
OnWorkEnd ist ein Event.
Du würdest doch auch bei einem TButton nicht schreibenif (Button1->OnClick == true)Also schau dir an was für Übergabeparameter der Event hat, oder ob der gelesene Wert in einer Eigenschaft der TIdTelnet-Komponente übergeben wird.
bis bald
akari
-
/Edit : sorry "bearbeiten" statt "zitieren" gedrückt...
-
Hallo
Ein Event wird doch durch irgendwas ausgelöst, normalerweise
Ja und du must den abfangen. Wie bei einem TButton.
Da wird doch bestimmt eine Art "Flag" gesetzt, nehme ich an.
Nein. Wenn du ein Flag willst must du es selber deklarieren und setzen. genau dafür wird der Event ja aufgerufen.
// Headerdatei class ... { ... bool m_workend; // Flag void __fastcall OnWorkEnd(...); // Hier Event-signatur aus BCB-Hilfe übernehmen }; // Implementation // Bei Anfang der Arbeit Flag zurücksetzen m_workend = false; // Und der Event verbunden IdTelnet->OnWorkEnd = OnWorkEnd; ... void __fastcall ...::OnWorkEnd(...) { m_workend = true; // Hier wird Flag gesetzt } ... // Flag abfragen if (m_workend) { }bis bald
akari
-
Hallo,
Flag selbst erstellen und dann abfragen, ich Danke Dir. Also kommt man an die eigentlichen Auslöser der Events so nicht ran (wär aber praktisch). Schade, es muss ja irgendwelche Zustandsspeicher / -bits geben, die gesetzt und abgefragt werden.
Zur Realisierung des Vorschlages:
* OnWorkEnd habe ich nur "gedoppelklickt" in IdTelnet, dann hat BDS das in *.h im __published-Bereich meiner Klasse hinzugefügt und in *.cpp das Gerüst für die Methode hinzugefügt
* bool m_workend (heißt nat. in meinem Prog etwas anders) habe ich im public-Bereich der *.h vom Hauptthread deklariert und im Konstruktor vom Hauptthread in der *.cpp mit false initialisiert
* in das automatisch erstellte Gerüst der Methode habe ich m_workend= true; eingefügt
*in der Methode zur Verarbeitung der empfangenen Daten habe ich ein Abfrage if (m_workend== true) setze Farbe des Statuslabel auf blau else setze Farbe des Statuslabel auf gelb
* IdTelnet->OnworkEnd= OnWorkEnd habe ich weggelassen, weil ich nicht sehe wozu das benötigt wird
- Richtig so?
Das Problem: Nach dem Empfang von Daten springt das Prog nicht in die Methode OnWorkEnd.Also habe ich versucht, das Flag im 2. Thread zu setzen (weil ich dachte, dass da vielleicht das Event wahrgenommen wird):
* m_workend im public-Bereich der *.h meines Hauptthread deklariert, damit ich es von überall nutzen kann und im Konstruktor des 2. Thread initialisiert
Fehlermeldung: undefiniertes Symbol
* also Flag zusätzlich in *.h des 2. Thread im public-Bereich deklariert (warum muss das so?)
nun weiß ich nicht weiter - ich schaff es einfach nicht die Methode ...WorkEnd dem Thread bekannt zu machen und wenn ich sie irgendwo anders als im __published-Bereich des Hauptthread deklariere, bekomm ich die Meldung "Die Methode IdTelnet1WorkEnd, auf die Idtelnet1->OnWorkEnd verweist, existiert nicht." - Folglich kann ich auf das Event ja im 2. Thread nicht mit einer Methode reagieren. Plan futsch.Nun bin ich wieder planlos...
MfG
-
Hallo,
ich muss das Thema leider nochmal rausholen. Hat denn noch keiner mit der Indy-Telnet-Komponente gearbeitet und kann mir dazu weitergehende Tips geben? Es läuft ja Alles ganz gut in meinem Prog, nur den Start der Verarbeitung der eingegangenen Daten würd ich halt gerne selbst steuern. Ich arbeite inzwischen wieder ohne eigenen Empfangs-Thread, da ja die Telnet-Komponente selbst einen Thread erzeugt und verwaltet (man muss nur die Eigenschaft "Threaded Event" auf true stellen
).Ich setz' einfach nochmal an: Wenn ich OnWorkEnd nutzen will, müsste ich vielleicht mit OnWorkBegin anfangen. Dazu steht in der Hilfe des BDS 2006:
Event handler signalled when beginning a read or write operation.
Ereignisbehandlung der gemeldet wird , wenn eine Lese- oder Schreiboperation gestartet wird. (1) Richtig übersetzt? Also sinngemäß: Direkt bevor Daten gesendet oder empfangen werden, kann ich mit dieser Ereignisbehandlung noch gewünschten Code ausführen. Weiterhin steht geschrieben (kommt mir vor wie n Bibelzitat - "Es steht geschrieben..."):
OnWorkBegin is a TWorkBeginEvent property...
OnWorkBegin ist eine Eigenschaft von TWorkBeginEvent... (2) Richtig? Also sinngemäß: Ich muss mir die Hilfe zu TWorkBeginEvent anschauen. Nun denn, da weiter. Zuerst steht dort mal:
Indicates a pending read or write operation.
Zeigt eine anstehende Lese- oder Schreiboperation an. (3) Richtig so? Weiterhin die Deklaration:
TWorkBeginEvent = procedure (ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer) of object;mit der Beschreibung:
ASender => Object instance triggering the event.
AWorkMode => The operation to be performed.
AWorkCountMax => The number of bytes expected for this operation.ASender => Komponente die das Event auslöst. (Also die TIdTelnet-Komponente)
AWorkMode => Auf welche Operation ist das Event eingestellt. (Also zB. Schreiben - "wmWrite")
AWorkCountMax => Anzahl der Datenbytes der Übertragung. (Also zB. 2 char's - 2 Byte. Oder 0 für "keine Ahnung" bzw. keine feste Anzahl)Nun zum praktischen Teil:
Ich doppelklicke also im Objektinspektor in den Ereignissen von TIdTelnet auf OnWorkBegin. Ich erhalte dadurch:
void __fastcall TIndyTelnetClient::IdTelnet1WorkBegin(TObject *Sender, TWorkMode AWorkMode, const int AWorkCountMax) { }und passe es auf meine Bedürfnisse an:
void __fastcall TIndyTelnetClient::IdTelnet1WorkBegin(TObject *Sender, TWorkMode wmWrite, int SL) { MessageBox ( void(), SL + " Byte werden nun gesendet...", \ "TxData", MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1); }Die MessageBox will ich haben, bevor Daten versendet werden. In Ihr soll stehen, wieviel Byte versendet werden. SL habe ich in private deklariert. Der Wert in SL wird je nach Länge der zu versendenden Daten vorher gesetzt. Die Methoden-Deklaration in [Edit]__published[/Edit]:
void __fastcall IdTelnet1WorkBegin(TObject *Sender, TWorkMode AWorkMode, const int AWorkCountMax);habe ich nicht verändert, weil es sonst immer die Meldung gibt: die Methode ... enthält eine inkompatible Parameterliste... Nun kann ich das Projekt ohne Fehlermeldung erzeugen. Wollen mal sehen was nun passiert, wenn ich tatsächlich Daten versende...

Nix! Keine MessageBox. Alles läuft wie gewohnt, ohne zusätzliche Ergebnisse. Als ob ich die Methode nie eingebaut hätte

Bitte helft mir.
MfG
-
Hallo
Benutzt mal den Debugger und schau ob die Eventmethode angesprungen wird.
Desweiteren bin ich überrascht das die Codezeile mit der MessageBox überhaupt kompiliert. Den einen Integer zu einem String-Literal zu addieren ist immer schlecht. Und der Backslash am Ende der ersten Zeile ist doch sicher auch nicht im echten Quellcode?
Der MessageBox-Aufruf wollte besser so aussehen :Application->MessageBox(IntToStr(SL) + " Byte werden nun gesendet...", "TxData", MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1);bis bald
akari
-
Hallo,
und Danke erstmal für die schnelle Antwort. Die Methode wird garnicht angesprungen. Habe jetzt die Deklaration noch in der Form abgeändert:
void __fastcall IdTelnet1WorkBegin(TObject *Sender, TWorkMode wmWrite, const int SL);Hilft aber auch nix.
Deinen Rat mit dem Integer nehm ich mir zu Herzen, hab ich gleich abgeändert. Das BackSlash verwende ich oft, hatte ich mir mal rausgesucht... Damit kann man die Zeilen umbrechen und der Befehl wird trotzdem als einzeilig angesehen. Andere MessageBoxen in meinem Prog funktionieren auch so.MfG
Edit: Die MessageBox funktioniert so nicht. Fehlermeldungen:
*[C++ Fehler] UNIGATE_CLIENT_OET01.cpp(340): E2034 Konvertierung von 'AnsiString' nach 'const char ' nicht möglich
*[C++ Fehler] UNIGATE_CLIENT_OET01.cpp(340): E2342 Keine Übereinstimmung des Typs beim Parameter 'Text' ('const char ' erwartet, 'AnsiString' erhalten)
Also:Application->MessageBox ( char(SL) + " Byte werden nun gesendet...", \ "TxData", MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1);...
-
Hallo Leute,
ich kann nur sagen: Asche über mein Haupt. Wie kann man nur so dämlich sein!?! Das Problem scheint im Ansatz gelöst. Ich habe mir jetzt das 20ste Mal die BDS2006 Hilfe zum Thema OnWork / -Begin / -End reingezogen und festgestellt, dass OnWorkBegin nur Aufgerufen wird, wenn ich die Methode IdTelnet->WorkBegin in meinem Prog irgendwo aufrufe (am Besten natürlich vor dem Senden oder Empfangen). So im nachhinein betrachtet macht das auch mehr als Sinn! OnWorkBegin wird also nicht automatisch angesprungen, sondern durch den Aufruf einer Methode.
BeginWork is a virtual procedure used to trigger the OnBeginWork event.
..wenn das nicht eindeutig ist...

Jedoch ist das kleine Problem mit der MessageBox noch offen. Ich habe eine variable vom Typ int, die in private deklariert ist. Der Inhalt / Wert dieser Variablen soll im Text meiner MessageBox mit ausgegeben werden. Wie geht das?
MessageBox ( void(), IntToStr(SL) + " Byte werden nun gesendet...", \ "TxData", MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1);funktioniert nicht.
Fehlermeldung: *[C++ Fehler] UNIGATE_CLIENT_OET01.cpp(328): E2342 Keine Übereinstimmung des Typs beim Parameter 'lpText' ('const char ' erwartet, 'AnsiString' erhalten)Ich müsste also wahrscheinlich den int-Wert in einen char-wert umwandeln oder?
MfG
-
Hallo
Nochmal mein Hinweis auf die VCL-eigene MessageBox-Funktion, die zwar intern auch nur die entsprechende WinAPI-Funktion aufruft aber dafür keinen Handle-Parameter braucht.
Und falls du auf deine WinAPI-Funktion bestehst solltest du auch nicht als Handle void() übergeben sondern 0 bzw. NULL.Das eigentliche Problem ist das du den zusammengesetzten AnsiString nun noch in einen char* umwandeln must
AnsiString Buffer = IntToStr(SL) + " Byte werden nun gesendet..."; Application->MessageBox(Buffer.c_str(), "TxData", MB_ICONINFORMATION | MB_OK | MB_DEFBUTTON1);bis bald
akari