AGB  ·  Datenschutz  ·  Impressum  







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

Ereignisse in der Konsole

Ein Thema von Schwedenbitter · begonnen am 29. Mai 2017 · letzter Beitrag vom 29. Mai 2017
Antwort Antwort
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

Ereignisse in der Konsole

  Alt 29. Mai 2017, 18:02
Hallo,

ich möchte gern aus einem Thread heraus erzeugte Ereignisse auf einem Konsoleprogramm empfangen können. Bedauerlicher Weise klappt das nicht. Egal ob ich nun eine Endlosschleife mittels Variable, mittels Messageloop oder - wie embarcadero es selbst nennt - mittels ReadLn; // Vor dem Schließen Konsole auf Pause setzen erzeuge, kommt nichts an.

Ich habe jetzt schon ein zweites Projekt angefangen, abgeleitet von TThread und habe langsam dieses Im Verdacht "Schuld" zu sein. Das Hauptprogramm sieht so aus:
Delphi-Quellcode:
Program DirThread.nonVCL;

{$APPTYPE CONSOLE}

Uses
   Winapi.Windows,
   System.SysUtils,
   DirPolling in '..\DirPolling.pas';

Type
   THelper   = Class
                  Procedure ShowChange(FileName: String);
              End;

Procedure THelper.ShowChange(FileName: String);
Begin
   WriteLn(FormatDateTime('yyyy.mm.dd hh:nn:ss ', Now) + FileName);
End;

Var
   Helper         : THelper;
   Msg            : TMsg;
Begin
   Helper:= THelper.Create;
   Try
      With TDirThread.Create('D:\', Helper.ShowChange) Do
      Try
         While GetMessage(Msg, 0, 0, 0) Do
         Begin
            TranslateMessage(Msg);
            DispatchMessage(Msg);
         End;
      Finally
         Free;
      End;
   Except
      On E: Exception Do Writeln(E.ClassName, ': ', E.Message);
   End;
   Helper.Free;
End.
Unter einem VCL-Programm kommt das Ereignis von folgendem Code sauber an:
Delphi-Quellcode:
nit DirPolling;

Interface

Uses
   System.SysUtils,
   System.Classes;

Type
   TDirEvent   = Procedure(FileName: String) Of Object;

   TDirThread   = Class(TThread)
                 Public
                     Constructor Create(Directory: String; OnChange: TDirEvent);
                     Destructor Destroy; Override;
                 Protected
                     fDir         : String;
                     fFileName   : String;
                     fOnChange   : TDirEvent;
                     fOldList      : TStringList;
                     Procedure FireEvent;
                     Procedure Execute; Override;
                 End;

Implementation

Constructor TDirThread.Create(Directory: String; OnChange: TDirEvent);
Begin
   fDir:= IncludeTrailingPathDelimiter(Directory);
   fFileName:= '';
   fOnChange:= OnChange;
   fOldList:= TStringList.Create;
   Inherited Create(False);
   Priority:= tpIdle;
End;

Destructor TDirThread.Destroy;
Begin
   fOldList.Free;
   Inherited;
End;

Procedure TDirThread.FireEvent;
Begin
   If Assigned(fOnChange) Then fOnChange(fDir + fFileName);
End;

Procedure TDirThread.Execute;
Var
   NewList         : TStringList;
   SR               : TSearchRec;
   I               : Integer;
Begin
   NewList:= TStringList.Create;
   Try
      While (Not Terminated) Do
      Begin
         If (FindFirst(fDir + '*.*', faAnyFile, SR) = 0) Then
         Repeat
            If (SR.Attr And faDirectory = 0) Then   // Verzeichnisse ignoroieren
                NewList.Append(SR.Name);            // zur Liste hinzufügen
         Until (FindNext(SR) <> 0) Or Terminated;   // bis nichts mehr gefunden wird
         FindClose(SR);                              // Speicher freigeben

         If (NewList.Count > 0) Then               // Gibt es Einträge?
         Begin
            NewList.Sort;                           // zuerst sortieren
            For I:= 0 To Pred(NewList.Count) Do      // ganze liste druchgehen
               If (fOldList.IndexOf(NewList[I]) = -1) Then
               Begin                                 // => neuer Eintrag gefunden
                  fFileName:= NewList[I];            // Dateinamen merken
                  Synchronize(FireEvent);            // Ereignis ausgeben
               End;
         End;

         fOldList.Text:= NewList.Text;               // neue = neue alte Liste
         NewList.Clear;                              // Liste löschen
         Sleep(10);                                 // kurz schlafen legen
      End;
   Finally
      NewList.Free;
   End;
End;

End.
Denselben Effekt habe ich - wie schon gesagt - mit einer Komponente auf Basis von TThread, die ReadDirectoryChanges() nutzt - in VCL alles schick und auf der Konsole kommen keine Ereignisse mehr an. Ich habe nun schon mehrere Codes in Suchmaschinen untersucht und kann die Ursache nicht finden. Möglicher Weise liegt es an den sprichwörtlichen Tomaten...
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.132 Beiträge
 
Delphi 12 Athens
 
#2

AW: Ereignisse in der Konsole

  Alt 29. Mai 2017, 18:37
Es kommt eben darauf an, wie das intern arbeitet.

Werden Messages verwendet oder sowas wie TThread.Synchronize, dann müssen diese Messages auch verarbeitet werden, was in einer Konsolenanwendung nunmal standardmäßig nicht passiert.
Also per se können erstmal nur Dinge netzt werden, welche mit Callback-Methoden arbeitet, die nicht über Messages ausgelöst werden.

Oder DU mußt selber für eine regelmäßige Verarbeitung der anfallenden Messages sorgen.


Da die VCL (GDI) mit Messages arbeitet, ist dort bereits eine automatische Verarbeitung implementiert. (welche nur stockt, wenn jemand im Hauptthread jenes für längere Zeit "blockiert")
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (29. Mai 2017 um 18:41 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#3

AW: Ereignisse in der Konsole

  Alt 29. Mai 2017, 20:36
Funktioniert es denn ohne das Synchronize ?

BTW:
Unter Windows gibt es extra APIs, die Änderungen im Dateisystem sehr effizient ohne Polling monitoren können: MSDN-Library durchsuchenFindFirstChangeNotification oder MSDN-Library durchsuchenSHChangeNotifyRegister
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Antwort Antwort


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 22:19 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