AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi [VCL] TCustomControl, Welche Methode für Komponente um empfangsbereit zu sein?
Thema durchsuchen
Ansicht
Themen-Optionen

[VCL] TCustomControl, Welche Methode für Komponente um empfangsbereit zu sein?

Ein Thema von 4dk2 · begonnen am 3. Apr 2017 · letzter Beitrag vom 3. Apr 2017
Antwort Antwort
4dk2

Registriert seit: 4. Sep 2007
176 Beiträge
 
#1

[VCL] TCustomControl, Welche Methode für Komponente um empfangsbereit zu sein?

  Alt 3. Apr 2017, 08:08
Delphi-Version: 10 Berlin
Guten morgen zusammen,


Ich habe ne Art Logging Komponente, die Thread-safe Log-Ereignisse empfangen kann, in einer oder mehreren Dateien hinterlegen kann, und an mehreren
Stellen anzeigen kann.

Die Komponente, die die Ereignisse Live anzeigt, bereitet mir im Moment ein paar Kopfschmerzen.

Und Zwar dann, wenn Ereignisse zur Create Phase der Anwendung passieren.
Ich habe mal eine Demo erstellt (siehe Anhang)

Aber Grundsätzlicht, habe ich eine TCustomPanel, auf der Eine Listbox erstellt wird, und dort werden per
AddLog Meldungen eingetragen.

im Addlog habe ich eine Sperre, das erst Meldungen angenommen werden, wenn die Komponente dazu bereit ist,
weil ohne Sperre kommen sehr merkwürdige Windows Fehler.
Mein Aktueller "Workarround" ist es, erst nach dem Aufruf vom Paint, Meldungen zu erlauben (FAddAllowed=true).

Ich würde euch jetzt gerne Fragen, wie ich am besten die Sperre aufhebe,
sozusagen, wann kann gefahrlos eingetragen werden?
Und wann kann sicher SendMessage() aufgerufen werden für den Autoscroll?

(Es geht gar nicht darum das evtl. Daten verloren gehen, in meiner eigentlichen Komponente wird das berücksichtigt.


Delphi-Quellcode:
unit uFMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls,SyncObjs, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, JvExStdCtrls, JvListBox;



type
  TTestLog=class(TCustomPanel)
  private
    FAddAllowed:boolean;
    FListBox:TListBox;
    FCS_Add:TCriticalSection;
    FWorkaroundActive: boolean;
  protected
    procedure Paint; override;


  public
    property WorkaroundActive:boolean read FWorkaroundActive write FWorkaroundActive;
    procedure AddLog(Amessage:string);
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

  end;

  TTestThread=class(TThread)
  private
    FLog:TTestLog;
  protected
    procedure Execute; override;
  public
    constructor Create(ALog:TTestLog);
    destructor Destroy; override;
    class procedure SicherFreigeben(var threadObjekt: TTestThread); static;

  end;

  TFMain = class(TForm)
    pb1: TPanel;
    btnStart: TButton;
    btnStop: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnStartClick(Sender: TObject);
    procedure btnStopClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    FLog:TTestLog;
    FT:array[0..100] of TTestThread;

    { Public-Deklarationen }
  end;

var
  FMain: TFMain;

CONST MAXTHREADS=10;


implementation

{$R *.dfm}

{ TTestLog }

procedure TTestLog.AddLog(Amessage: string);
begin
  FCS_Add.Enter;
  try
    if FAddAllowed or not FWorkaroundActive then
    begin
      FListBox.Items.Add(Amessage);

      SendMessage(FListBox.Handle, LB_SETTOPINDEX, FListBox.Items.Count-1, 0);
      FListBox.Update;
      self.Update;
    end;
  finally
    FCS_Add.Leave;
  end;
end;

constructor TTestLog.Create(AOwner: TComponent);
begin
  inherited;
  FCS_Add:=TCriticalSection.Create;
  FListBox:=TListBox.Create(self);
  FListBox.Parent:=self;
  FListBox.Align:=alClient;
  FListBox.Color:=clBlack;
  FListBox.Font.Color:=clWhite;
end;

destructor TTestLog.Destroy;
begin
  FCS_Add.Free;
  FListBox.Free;
  inherited;
end;

procedure TTestLog.Paint;
begin
  inherited;
  if FWorkaroundActive then
    FAddAllowed:=true;
end;


{ TTestThread }



constructor TTestThread.Create(ALog: TTestLog);
begin
  inherited Create(false);

  FLog:=ALog;

end;

destructor TTestThread.Destroy;
begin
  FLog:=nil;
  inherited;
end;

procedure TTestThread.Execute;
begin

  while not Terminated do
  begin
    if Assigned(FLog) then
      FLog.AddLog('THREAD: '+inttostr(ThreadID)+' TESTLOG');
    sleep(100);
  end;

end;

class procedure TTestThread.SicherFreigeben(var threadObjekt: TTestThread);
begin
  if assigned(threadObjekt) then
  begin
    threadObjekt.Terminate;
    threadObjekt.WaitFor;
    threadObjekt.free;
    threadObjekt:=nil;
  end;
end;


procedure TFMain.btnStartClick(Sender: TObject);
var
  I: Integer;
begin
  for I := low(ft) to MAXTHREADS-1 do
    FT[i]:=TTestThread.Create(FLog);


end;

procedure TFMain.btnStopClick(Sender: TObject);
var
  I: Integer;
begin
  for I := low(ft) to MAXTHREADS-1 do
  begin
    FT[i].SicherFreigeben(FT[i]);
  end;

end;
procedure TFMain.FormCreate(Sender: TObject);
begin
 //
 FLog:=TTestLog.Create(self);
 FLog.Parent:=self;
 FLog.Align:=alClient;

 //Hier ist mein aktueller Workaround:
 //Wenn True, darf erst was hinzugefügt werden, wenn Paint aufgerufen wurde
 //auf False setzen um die Windows Fehler zu sehen ;)
 FLog.WorkaroundActive:=true;

 btnStartClick(self);
end;

procedure TFMain.FormDestroy(Sender: TObject);
begin
 btnStopClick(self);
end;

end.
Angehängte Dateien
Dateityp: zip DpLogTest.zip (53,9 KB, 1x aufgerufen)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.074 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: [VCL] TCustomControl, Welche Methode für Komponente um empfangsbereit zu sein?

  Alt 3. Apr 2017, 08:43
Delphi-Quellcode:
procedure TTestLog.AddLog(const AMessage: string);
begin
  FListBox.Items.Add(AMessage);

  SendMessage(FListBox.Handle, LB_SETTOPINDEX, FListBox.Items.Count-1, 0);
  FListBox.Update;
  self.Update;
end;


procedure TTestLog.AddLogThreadSafe(const AMessage: string);
begin
  if TThread.CurrentThread.ThreadID = MainThreadID then
  begin
    AddLog(AMessage)
  end
  else
  begin
    TThread.Queue(nil,
      procedure
      begin
        AddLog(AMessage);
      end);
  end;
end;
Probiere mal so und rufe zum Loggen nur AddLogThreadSafe auf.
  Mit Zitat antworten Zitat
4dk2

Registriert seit: 4. Sep 2007
176 Beiträge
 
#3

AW: [VCL] TCustomControl, Welche Methode für Komponente um empfangsbereit zu sein?

  Alt 3. Apr 2017, 08:57
Danke für die schnelle Antwort.
Klappt.
Aber, mich würde trotzdem noch interessieren, wann bei meiner Methode, die Komponente einsatzbereit wäre.

Z.b. wegen Abwärtskompatibilität (D7 usw).
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.074 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: [VCL] TCustomControl, Welche Methode für Komponente um empfangsbereit zu sein?

  Alt 3. Apr 2017, 09:11
Na ja, der Ansatz ist halt schon etwas auf dünnen Eis gebaut.
Einfach mal das Forum nach dem Stichwörtern Mainthread, VCL und threadsafe abklappern, zum Beispiel hier:
http://www.delphipraxis.net/179429-v...read-save.html
http://www.delphipraxis.net/83472-th...l-zugriff.html

Für D7 kannste auch GetCurrentThreadId aus der Windows.pas nehmen.
  Mit Zitat antworten Zitat
4dk2

Registriert seit: 4. Sep 2007
176 Beiträge
 
#5

AW: [VCL] TCustomControl, Welche Methode für Komponente um empfangsbereit zu sein?

  Alt 3. Apr 2017, 09:38
Na ja, der Ansatz ist halt schon etwas auf dünnen Eis gebaut.
...
Für D7 kannste auch GetCurrentThreadId aus der Windows.pas nehmen.
Bei D7 gab es das Queing noch nicht.

Ich bin bei der Komponenten Programmierung einfach nicht tief genug drin
  Mit Zitat antworten Zitat
4dk2

Registriert seit: 4. Sep 2007
176 Beiträge
 
#6

AW: [VCL] TCustomControl, Welche Methode für Komponente um empfangsbereit zu sein?

  Alt 3. Apr 2017, 10:35
Hab jetzt noch nen paar themen, und auch eine links dazu gelesen, und du hast recht es
ist einfach nur sinvoll wenn man es per:

Antwort: Queue oder Synchronize benutzen

macht,
für D7 geht das hier dann:
http://www.uweraabe.de/Blog/2011/01/...th-parameters/
  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 08:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz