Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Auf Procedure warten ?
Blamaster - Sa 05.07.08 11:47
Titel: Auf Procedure warten ?
Hi,
wie kann man in Delphi auf eine Procedure warten ?
Folgendes soll passieren.
Ich habe jetzt mal beispielsweise folgenden code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| procedure TForm1.SerialPortNG1RxClusterEvent(Sender: TObject); begin Rs232in:= SerialPortNG1.ReadNextClusterAsString; end;
end;
procedure TForm1.Button5Click(Sender: TObject); begin SerialPortNG1.SendString('sendcues'+#$0d#$0a); AUF BEGINN UND ENDE DER PROCEDURE WARTEN SerialPortNG1.SendString('20'+#$0d#$0a); AUF BEGINN UND ENDE DER PROCEDURE WARTEN SerialPortNG1.SendString('5'+#$0d#$0a); AUF BEGINN UND ENDE DER PROCEDURE WARTEN SerialPortNG1.SendString('6'+#$0d#$0a); AUF BEGINN UND ENDE DER PROCEDURE WARTEN SerialPortNG1.SendString('2'+#$0d#$0a); end; |
procedure TForm1.SerialPortNG1RxClusterEvent wird angesprungen, wenn über den Com Port daten an den Pc gesendet werden.
Wenn ich den Button klicke soll SerialPortNG1.SendString('sendcues'+#$0d#$0a); ausgeführt werden und danach gewartet werden bis SerialPortNG1RxClusterEvent angesteuert und beendet wird. Erst dann soll SerialPortNG1.SendString('20'+#$0d#$0a); ausgeführt werden. Danach wieder das selbe spielchen, bis das ende der Button5Click Procedure erreicht ist.
mfg blamaster
Yogu - Sa 05.07.08 12:13
Normalerweise kann in Delphi immer nur
eine Prozedur ausgeführt werden, d.h. es wird immer gewartet, bis eine Anweisung abgeschlossen ist. Vielleicht wird aber in der Prozedur, die du aufrufst, ein neuer Thread gestartet. In diesem Fall wird die Prozedur danach sofort verlassen, und die Anweisungen in dem Thread parallel zu deinem Hauptthread ausgeführt. Vielleicht solltest du dir mal, wenn vorhanden, den Quelltext der Prozedur
SendString anschauen.
Wenn du bereit wärst, die Komponente zu ändern, dann könntest du dir auch mal
comm_async [
http://www.delphi-forum.de/viewtopic.php?p=447813#447813] anschauen. Da werden die Daten erst komplett gesendet, bevor die Programmausführung weitergeht.
Blamaster - Sa 05.07.08 12:32
Das Problem war bisher immer folgendes:
Wenn ich Daten mit Delphi (obige procedure) an den Microcontroller geschickt habe, führte das zu einem Datenchaos, das Delphi scheinbar alles zu sendenden strings sofort rausgeballert hat. Deswegen dachte ich mir nun soll der erste String gesendet werden. Daraufhin schickt der Microcontroller den empfangenen String wieder an den Pc zurück, damit das Delphi Programm weiß, das der String definitiv nun erfolgreich gesendet wurde. Dann soll es halt den nächsten String schicken und wieder auf bestätigung warten.
Hat da jemand von euch ne elegante Lösung für das Problem ?
mfg Blamaster
Yogu - Sa 05.07.08 12:42
Du könntest eine Variable definieren, die immer den gesendeten String enthält. Nach dem Senden des Strings gehst du in eine Schleife, die darauf wartet, dass dieser String leer wird.
Im Ereignis "String empfangen" überprüfst du, ober der String dem gesendeten entspricht. Wenn das der Fall ist, wird die Variable geleert (was dazu führt, dass die Sendemethode weitermacht. Falls der String falsch ist oder ein Timeout in der Warteschleife auftritt, wird ein Fehler gemeldet.
Blamaster - Sa 05.07.08 13:26
Hi, das hört sich shconmal super an. Kannst du das an ein bisschen code bildlich machen kann mir das gerade noch nicht so ganz wirklich vorstellen.
mfg Blamaster
Yogu - Sa 05.07.08 13:41
Ok, ich versuch's mal...
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59:
| type TForm1 = class(TForm) private SendedString: String;
procedure SendString(const S: String); end;
ESerialPortError = Exception;
const Timeout = 1000;
procedure TForm1.SendString(const S: String); var Time: Cardinal; begin SerialPortNG1.SendString(S + #$0D#$0A);
Time := GetTickCount; while Time+Timeout > GetTickCount do if SendedString = '' then Break;
if SendedString <> '' then raise ESerialPortError.Create('Gegenseite antwortet nicht'); end;
procedure TForm1.Button5Click(Sender: TObject); begin SendString('sendcuess'); SendString('20'); SendString('5'); SendString('6'); SendString('2'); end;
procedure TForm1.SerialPortNG1RxClusterEvent(Sender: TObject); var S: String; begin S := SerialPortNG1.ReadNextClusterAsString;
if S = SendedString then SendedString := '' else raise ESerialPortError.Create('Gegenstelle lieferte ungültige Antwort'); end; |
Wenn ein Fehler auftritt, sorgt Delphi dafür, dass die gesamte Prozedur abbricht. Du solltest ihn jedoch noch mit
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| try except on E: ESerialPortError do Application.MessageBox(PChar('Fehler beim Senden eines Strings: '+E.Message), 'Fehler', MB_ICONERROR); end; |
oder etwas ähnlichem irgendwo abfangen.
Blamaster - Sa 05.07.08 15:58
Hi,
Thx erstmal.
Also so ganz funzen wollte der code so noch nicht. Ich habe ihn für Testzwecke etwas abgespeckt gehabt. also die abgleiche zwischen gesendetem und ankommendem strings entfernt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| procedure TForm1.SendString(const S: String); var Time: Cardinal; begin SerialPortNG1.SendString(S + #$0D#$0A); Time := GetTickCount; while Time+Timeout > GetTickCount do if SendedString = '' then Break; if SendedString <> '' then raise ESerialPortError.Create('Gegenseite antwortet nicht'); end;
procedure TForm1.Button5Click(Sender: TObject); begin SendString('20'); SendString('5'); SendString('6'); SendString('2'); end;
procedure TForm1.SerialPortNG1RxClusterEvent(Sender: TObject); var S: String; begin S := SerialPortNG1.ReadNextClusterAsString; ShowMessage(S); SendedString := '' end; |
Wenn ich jetzt button 5 klicke sendet er die 20 diese bekomme ich dann auch über das ShowMessage(S); die 20 wieder zurückgegeben. Danach scheint er aber die weiteren SendString nicht mehr abzuarbeiten.
Woran kann das liegen ?
Edit. Habe jetzt nochwas getestet
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure TForm1.Button5Click(Sender: TObject); begin SendString('20'); ShowMessage('1'); SendString('5'); ShowMessage('2'); SendString('6'); ShowMessage('3'); SendString('2'); end; |
Wenn ich nun Button 5 klicke erreiche ich jedes Show Message und die werte werden auch alle an den controller gegeben.
Ich vermute also mal das es mit dem timing noch nicht klappt. Woran merkt den das programm momentan ob der µC die Daten auch verarbeitet hat und wieder empfangsbereit ist ?
Yogu - So 06.07.08 12:22
Zuerst mal, dass es hier keine Missverständnisse geben wird:
Blamaster hat folgendes geschrieben: |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure TForm1.SendString(const S: String); var Time: Cardinal; begin SerialPortNG1.SendString(S + #$0D#$0A); Time := GetTickCount; while Time+Timeout > GetTickCount do if SendedString = '' then Break; if SendedString <> '' then raise ESerialPortError.Create('Gegenseite antwortet nicht'); end; | |
Die markierte Zeile solltest du um eine Stelle ausrücken, die gehört nicht in die Schleife, sonst bräuchtest du ja ein
begin ... end. In der Schleife wird einfach nur geprüft, ob der String inzwischen leer ist (also die Empfangs-Prozedur erfolgreich war). Weil ja auch ein Timeout auftreten kann (im Schleifenkopf definiert), muss am Schluss noch der Grund geprüft werden, warum die Schleife verlassen wurde. Sollte ein Timeout aufgetreten sein, ist ja die Variable noch nicht leer.
Blamaster hat folgendes geschrieben: |
Woran merkt den das programm momentan ob der µC die Daten auch verarbeitet hat und wieder empfangsbereit ist ? |
Der Microcontroller sendet die Daten doch erst wieder zurück, wenn er sie komplett ausgewertet hat, oder? Die Schleife wartet ja darauf, dass sie wieder zurückgesendet werden. Natürlich gehe ich davon aus, dass er dann wieder Aufnamefähig ist.
Vielleicht hilft ein
Application.ProcessMessages in der Schleife - das könntest du mal ausprobieren.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!