AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Tserial abschiessen

Ein Thema von mymuschy · begonnen am 17. Aug 2006 · letzter Beitrag vom 18. Aug 2006
Antwort Antwort
Seite 1 von 2  1 2      
mymuschy

Registriert seit: 13. Apr 2004
Ort: Elchingen
19 Beiträge
 
Delphi 7 Enterprise
 
#1

Tserial abschiessen

  Alt 17. Aug 2006, 12:04
Hallo,

ich kommuniziere per Tserial mit einem externen Gerät das über die Serielle Schnittstelle ständig nur am Senden ist. Empfangen wird dieses Dauerfeuer per:
Delphi-Quellcode:
procedure TSS.tC_SerialRxData(Sender: TObject);
  Var C : Char;
begin
  While tC_Serial.ReadChar(C)>0 do Begin
    Case C of
      #2 : HS:='';
      #3 : Begin
             tC_String:=HS;
           End;
      Else If Length(HS)<100 Then HS:=HS+C;
    End;
  End;
end;
Jetzt hab ich das Problem das das Beenden des Programms ehwig dauert, obwohl ich die Schnittstelle mit:
tC_Serial.Active:=false; schliesse.

Stecke ich mein externes Gerät aus schliesst das Programm sofort.

Gibt es eine Möglichkeit die TSerial Komponente sofort zu schliessen?
Gruß

Stephan
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#2

Re: Tserial abschiessen

  Alt 17. Aug 2006, 12:06
Das Problem ist, dass Dein Programm in der Schleife steckt
und keine Systemmeldungen verarbeitet.

Delphi-Quellcode:
procedure TSS.tC_SerialRxData(Sender: TObject);
  Var C : Char;
begin
  While tC_Serial.ReadChar(C)>0 do Begin
    Application.ProcessMessages; // <----
    Case C of
      #2 : HS:='';
      #3 : Begin
             tC_String:=HS;
           End;
      Else If Length(HS)<100 Then HS:=HS+C;
    End;
  End;
end;
Könnte vielleicht etwas Abhilfe bringen.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
mymuschy

Registriert seit: 13. Apr 2004
Ort: Elchingen
19 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: Tserial abschiessen

  Alt 17. Aug 2006, 12:30
Hallo Klaus01,

bringt leider auch nichts! Ich hab auch schon versucht in die Schleifenbedingung eine zweite Bedingung einzubauen.
Delphi-Quellcode:
procedure TSS.tC_SerialRxData(Sender: TObject);
  Var C : Char;
begin
  While (tC_Serial.ReadChar(C)>0) and not sofort_beenden do Begin
    Case C of
      #2 : HS:='';
      #3 : Begin
             tC_String:=HS;
           End;
      Else If Length(HS)<100 Then HS:=HS+C;
    End;
  End;
end;
Die boolsche Variable "sofort_beenden" wird beim schliesen im OnClose Ereignis auf true gesetzt.

Aber leider auch ohne Erfolg...

Ist es vielleicht möglich den Empfang komplett zu unterbinden?
Gruß

Stephan
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#4

Re: Tserial abschiessen

  Alt 17. Aug 2006, 12:53
Kannst Du mal einen Breakpoint in Deinem OnClose Ereignis setzen.
Und dann mal schauen ob direkt nach der Beendigung des Programms
da hinein gesprungen wird.
Wenn es da auch schon länger dauert, dann hängt Dein Programm
vielleicht noch woanders in der Verarbeitung fest.

Wenn Du die Zeichen von der Schnittstelle gelesen hast,
mußt Du dann nich das Puffer der Schnittstelle leeren?

Das würde mit ZapRXQueue gehen.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
mymuschy

Registriert seit: 13. Apr 2004
Ort: Elchingen
19 Beiträge
 
Delphi 7 Enterprise
 
#5

Re: Tserial abschiessen

  Alt 17. Aug 2006, 13:11
Er spring beim schliessen sofort "rein" und erst nach ca. 10sek. "raus"

Delphi-Quellcode:
procedure TSS.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  showmessage('rein');
  tC_Serial.Active:=false;
  showmessage('raus');
end;
Zitat:
Wenn Du die Zeichen von der Schnittstelle gelesen hast,
mußt Du dann nich das Puffer der Schnittstelle leeren?
Ich bin immer davon ausgegangen das readChar das Zeichen aus dem Puffer schmeisst. Weil der nächste Aufruf von readChar holt sich ja auch das nächste Zeichen.


Ich habs mal so versucht:
Delphi-Quellcode:
procedure TSS.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  showmessage('rein');
  tc_serial.ZapRxQueue;
  tC_Serial.Active:=false;
  showmessage('raus');
end;
Aber leider immer noch das gleiche Spiel...
Gruß

Stephan
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#6

Re: Tserial abschiessen

  Alt 17. Aug 2006, 13:14
Delphi-Quellcode:
procedure TSS.tC_SerialRxData(Sender: TObject);
  Var C : Char;
begin
  While (tC_Serial.ReadChar(C)>0) and not sofort_beenden do Begin
    tc_serial.ZapRxQueue; // wenn dann hier den Puffer löschen

    Case C of
      #2 : HS:='';
      #3 : Begin
             tC_String:=HS;
           End;
      Else If Length(HS)<100 Then HS:=HS+C;
    End;
  End;
end;
Nach dem Einlesen, werden die Date da noch verarbeitet?

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#7

Re: Tserial abschiessen

  Alt 17. Aug 2006, 13:19
Hi,
ich bin nicht ganz sicher, ob dein Design so sauber ist.
Ich geh hier einfach mal davon aus, dass tC_SerialRxData eine Ereignisbehandlung ist, die aufgerufen wird, sobald Daten ankommen. Hier liegt dann schon eines deiner möglichen Probleme. Die Kommunikation dürfte wohl asynchron sein, dass heißt natürlich, dass du gar nicht weißt wann welches Datum ankommt. Beendest du also die Ereignisbehandlung und es kommen neue Daten an, so wird die Methode sofort wieder aufgerufen. An sich solltest du auch keine Schleife in einer solchen Behandlung setzen. Imho müsstest du hier vielmehr eine eigene Methode verwenden, in der die Schleife läuft.
Was dein Problem mit dem Schließen angeht, versuch einfach mal die Ereignisbehandlung im onClose abzuschalten (tC_SerialRxData := nil) und dann noch die Schleife abbzubrechen (mit einem Flag).


Gruß Der Unwissende
  Mit Zitat antworten Zitat
mymuschy

Registriert seit: 13. Apr 2004
Ort: Elchingen
19 Beiträge
 
Delphi 7 Enterprise
 
#8

Re: Tserial abschiessen

  Alt 17. Aug 2006, 13:36
@Klaus01
habs mit
tc_serial.ZapRxQueue; versucht.
Ja es wird noch korrekt empfangen. Aber das Problem ist nicht weg.

@unwissender
Des mit der eigenen Funnktion versuch ich mal.
Wobei mir nicht klar ist warum ein Flag in einer eigenen Funktion, in der eine Schleife läuft, anders ist als ein Flag in der Schleife selbst.

Das mit der
Zitat:
Ereignisbehandlung im onClose abzuschalten (tC_SerialRxData := nil)
hab ich leider nicht verstanden. Wie geht denn das?
Gruß

Stephan
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#9

Re: Tserial abschiessen

  Alt 17. Aug 2006, 13:52
Deine Methode tC_SerialRxData wird immer dann aufgerufen, wenn Daten da sind. Wenn du also innerhalb dieser Methode sagst "stopp, will keine daten mehr", dann hat das überhaupt keine bedeutung, weil das event ja gleich wieder ausgelöst wird. du musst also das event komplett abschalten. und das geht so, wie Der_Unwissende es gesagt hat.
Lukas Erlacher
Suche Grafiktablett. Spenden/Gebrauchtangebote willkommen.
Gotteskrieger gesucht!
For it is the chief characteristic of the religion of science that it works. - Isaac Asimov, Foundation I, Buch 1
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#10

Re: Tserial abschiessen

  Alt 17. Aug 2006, 13:52
Zitat von mymuschy:
@unwissender
Des mit der eigenen Funnktion versuch ich mal.
Wobei mir nicht klar ist warum ein Flag in einer eigenen Funktion, in der eine Schleife läuft, anders ist als ein Flag in der Schleife selbst.
Oh, dann hab ich mich unklar ausgedrückt, ein Flag läuft hier genau wie in deiner Methode, es ist nur absolut unsauber die Behandlungsroutine mit einer Schleife zu verwenden!
Stell dir einfach mal vor, du bekommst 200 Byte gesendet. Da die Kommunikation asynchron ist, kommen die Bytes zufällig an. Nehmen wir mal den Fall an, es kommen erst 100 Byte, die lösen dein Event aus, es wird also einmal die Schleife gestartet und in Ruhe abgearbeitet. Währenddessen kommen nun auch irgendwann die nächsten 100 Byte an, jetzt wird wieder das Ereignis ausgelöst und hier läuft dann wieder das gleiche ab. Du reagierst also zweimal auf das Eintreffen von Daten in den Puffer.
Natürlich kannst du bei asynchroner Kommunikation nie sagen wann wieviele Daten im Puffer landen, also ist es garantiert nicht das von dir erwünschte Verhalten!
Wenn du jetzt aber eine eigene Methode verwendest, dann kannst du diese z.B. in einen Thread auslagern. Läuft dieser schon, dann liest der noch den aktuellen Puffer (und auch neu hinzukommende Zeichen) ein. Läuft der noch nicht, schmeißt du ihn an. Du kannst hier leicht abfangen, dass für jedes eintreffen von Daten ein eigener Thread gestartet wird.
Beendest du dann dein Programm, wird der Thread auch einfach nicht mehr neu gestartet (nur ein Beispiel einer möglichen Lösung). An den Flags ändert das natürlich nichts!

Zitat von mymuschy:
Das mit der
Zitat:
Ereignisbehandlung im onClose abzuschalten (tC_SerialRxData := nil)
hab ich leider nicht verstanden. Wie geht denn das?
Nun ja, Delphi verwendet um das Eintreten eines Ereingis zu signalisieren einen Methodenzeiger. Hier kannst du die Adresse einer Methode eintragen, die der erwarteten entspricht (also die richtigen Argumente hat). Tritt das Ereignis auf, wird geschaut ob die Adresse der Methode ungleich nil ist und wenn dies der Fall ist, wird die Methode mit der gespeicherten Adresse aufgerufen.
Wenn du im Objektinspektor doppelt auf ein Ereignis klickst, so wird für dich eine fertige Methode angelegt und der Editor springt in den Körper rein.
Hinter den Kulissen wird dabei einfach die Adresse dieser Methode als Methodenzeiger für das Ereignis gespeichert. Deswegen steht im Objektinspektor dann der Name der Methode.
Wenn du nun im Programm im OnCloseQuery einfach schreibst:
tc_serial.OnRxChar := nil; dann wird die Ereignisbehandlung abgeschaltet. Kommt jetzt ein neues Zeichen im Puffer an, gibt es keinen der benachrichtigt wird.

Sauberer und mehr OO wäre es, auf der Ereignisbehandlung einfach ein Observer-Pattern (bzw. eine Implementierung dieses Pattern) aufzusetzen. Aber das ist dann noch eine andere Sache.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz