TPanel i Thread = klasa

0

Witam,
mam taki kod:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;


type
  TRepThread = class(TThread)
  private
    FRepVal: Integer;
  protected
    procedure Execute; override;
  public
    constructor Create(RepVal : Word);
  end;

type
  TMyPanel = class(TPanel)
  private
    { Private declarations }
    FRep: Word;
    RepTimerThread : TRepThread;

  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner : TComponent; RepTime: Word);
    destructor Destroy; override;
  published
    { Published declarations }
  end;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TRepThread.Create(RepVal : Word);
begin
  inherited Create(False);
  FRepVal := RepVal;
end;

procedure TRepThread.Execute;
begin
FreeOnTerminate := True;
while not (Application.Terminated) or (Terminated) do
  begin
    Sleep(FRepVal);
  end;
end;


constructor TMyPanel.Create(AOwner : TComponent; RepTime: Word);
begin
  inherited Create(AOwner);

  FRep:=RepTime;

  Self.DoubleBuffered:=true;
  Self.Height:=200;
  Self.Width:=200;
  Self.Parent:=TWinControl(AOwner);

  RepTimerThread:=TRepThread.Create(FRep);

end;

destructor TMyPanel.Destroy;
begin
  RepTimerThread.Terminate;
  RepTimerThread.Free;
  inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
TMyPanel.Create(Form1,1000);
end;

end.

Jak widać staram się stworzyć własną klasę dziedzicząc po Tpanel oraz w niej wątek który będzie cyklicznie pobierał kilka informacji z bazy danych i wyświetlał w tym panelu.
Problem mam z tym że jak zamykam program to proces nadal wisi i nie wiem dlaczego, czy możecie mi wskazać gdzie robię błąd ?
Jak pewnie zauważycie robię dziwne konstrukcje typu FreeOnTerminate := True;
a i tak w destruktorze Panela wykonuję RepTimerThread.Terminate;
RepTimerThread.Free; Takie egzotyczne konstrukcje powstały w akcie mojej desperacji.
Poradźcie mi w czym jest błąd.
Pozdrawiam

0

while not (Application.Terminated or Terminated) do

albo

while not Application.Terminated and not Terminated do

0

Dziękuję za odpowiedź, faktycznie miałem błąd, przedstawiony problem rozwiązany, ale mam kolejny :/
kiedy zamykam program dostaję komunikat

First chance exception at $7C80BEE7. Exception class EThread with message 'Thread Error: Nieprawidłowe dojście (6)'. Process Project1.exe (1904)

O co w nim chodzi ?

0

daj kod całego execute

0
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;


type
  TRepThread = class(TThread)
  private
    FRepVal: Integer;
  protected
    procedure Execute; override;
  public
    constructor Create(RepVal : Word);
  end;

type
  TMyPanel = class(TPanel)
  private
    { Private declarations }
    FRep: Word;
    RepTimerThread : TRepThread;

  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner : TComponent; RepTime: Word);
    destructor Destroy; override;
  published
    { Published declarations }
  end;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TRepThread.Create(RepVal : Word);
begin
  inherited Create(False);
  FRepVal := RepVal;
end;

procedure TRepThread.Execute;
begin
FreeOnTerminate := True;
while not (Application.Terminated or Terminated) do
  begin
    Sleep(FRepVal);
  end;
end;


constructor TMyPanel.Create(AOwner : TComponent; RepTime: Word);
begin
  inherited Create(AOwner);

  FRep:=RepTime;

  Self.DoubleBuffered:=true;
  Self.Height:=200;
  Self.Width:=200;
  Self.Parent:=TWinControl(AOwner);

  RepTimerThread:=TRepThread.Create(FRep);

end;

destructor TMyPanel.Destroy;
begin
  RepTimerThread.Terminate;
  RepTimerThread.Free;
  inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
TMyPanel.Create(Form1,1000);
end;

end.

Jest to jak na razie cały kod programu, dopiero poznaję zasadę posługiwania się wątkami.
Bardzo proszę o pomoc.
Pozdrawiam

0

usuń to RepTimerThread.Free;

0

Bardzo dziękuję za pomoc Misiekd.

Mam jeszcze pytanie jak z klasy mojego wątka dostać się do MyPanel, chciałbym na razie co sekundę pobierać czas z systemu i wypisać w Label-u na tym panelu, jaśniej zapisałem to w kodzie poniżej.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;


type
  TRepThread = class(TThread)
  private
    FRepVal: Integer;
  protected
    procedure Execute; override;
  public
    constructor Create(RepVal : Word);
  end;

type
  TMyPanel = class(TPanel)
  private
    { Private declarations }
    FRep: Word;
    RepTimerThread : TRepThread;
    label1 : TLabel;
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner : TComponent; RepTime: Word);
    destructor Destroy; override;
  published
    { Published declarations }
  end;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TRepThread.Create(RepVal : Word);
begin
  inherited Create(False);
  FRepVal := RepVal;
end;

procedure TRepThread.Execute;
begin
FreeOnTerminate := True;
while not (Application.Terminated or Terminated) do
  begin
    Sleep(FRepVal);
    // Jak z tego miejsca odwolac sie do Label-a w klasie MyPanel
    // np. ...Label1.Caption:=timetostr(now);
  end;
end;


constructor TMyPanel.Create(AOwner : TComponent; RepTime: Word);
begin
  inherited Create(AOwner);

  FRep:=RepTime;

  Self.DoubleBuffered:=true;
  Self.Height:=200;
  Self.Width:=200;
  Self.Color:=clRed;
  Self.Parent:=TWinControl(AOwner);
  Self.Visible:=true;

  label1:=TLabel.Create(Self);
  label1.Parent:=Self;
  label1.Top:=80;
  label1.Left:=80;
  label1.Width:=100;
  label1.Height:=30;
  label1.Visible:=true;

  RepTimerThread:=TRepThread.Create(FRep);


end;

destructor TMyPanel.Destroy;
begin
  RepTimerThread.Terminate;
  label1.Free;
  inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
TMyPanel.Create(Form1,1000);
end;

end.
0
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;


type
  TPomazPanel = procedure(Text: string) of object;

  TRepThread = class(TThread)
  private
    FRepVal: Integer;
	FPomazPanel: TPomazPanel;
	FText: string;
	procedure DoPomazPanel;
  protected
    procedure Execute; override;
  public
    constructor Create(RepVal : Word);
	property OnPomazPanel: TPomazPanel read FPomazPanel write FPomazPanel;
  end;

type
  TMyPanel = class(TPanel)
  private
    { Private declarations }
    FRep: Word;
    RepTimerThread : TRepThread;
    label1 : TLabel;
	procedure PomazPanel(Text: string);
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner : TComponent; RepTime: Word);
    destructor Destroy; override;
  published
    { Published declarations }
  end;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TRepThread.Create(RepVal : Word);
begin
  inherited Create(False);
  FRepVal := RepVal;
end;

procedure TRepThread.Execute;
begin
FreeOnTerminate := True;
while not (Application.Terminated or Terminated) do
  begin
    Sleep(FRepVal);
    FText := timetostr(now);
	Synchronize(DoPomazPanel);
  end;
end;

procedure TRepThread.DoPomazPanel;
begin
  if Assigned(FPomazPanel) then
    FPomazPanel(FText);
end;

constructor TMyPanel.Create(AOwner : TComponent; RepTime: Word);
begin
  inherited Create(AOwner);

  FRep:=RepTime;

  Self.DoubleBuffered:=true;
  Self.Height:=200;
  Self.Width:=200;
  Self.Color:=clRed;
  Self.Parent:=TWinControl(AOwner);
  Self.Visible:=true;

  label1:=TLabel.Create(Self);
  label1.Parent:=Self;
  label1.Top:=80;
  label1.Left:=80;
  label1.Width:=100;
  label1.Height:=30;
  label1.Visible:=true;

  RepTimerThread:=TRepThread.Create(FRep);
  RepTimerThread.OnPomazPanel := PomazPanel;

end;

procedure TMyPanel.PomazPanel(Text: string);
begin
  label1.Caption := Text;
end;

destructor TMyPanel.Destroy;
begin
  RepTimerThread.Terminate;
  label1.Free;
  inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
TMyPanel.Create(Form1,1000);
end;

end.
0

Misiekd bardzo dziękuję, naprawdę łebski z Ciebie gościu.
Pozdrawiam

0

Witam raz jeszcze,
pojawił się natępny problem...
Gdy w OnCreate głównej formy dodałem ReportMemoryLeaksOnShutdown:=true;
po zakończeniu programu dostaje komunikat treści:

An unexpected memory leak has occurred. The unexpected small block leaks are:
13-20 bytes: String x 1
77-84 bytes: TRepThread x 1

a następnie pojawia się kolejne okno z komunikatem

Runtime error 216 at 00403A16

Prosił bym o wskazanie gdzie jest wyciek/błąd w programie.
Pozdrawiam

0

Zmień na

destructor TMyPanel.Destroy;
begin
  RepTimerThread.Terminate;
  WaitForSingleObject(RepTimerThread.Handle, INFINITE); //tu czeka na zakończenie wątku
  label1.Free;
  inherited;
end;

procedure TRepThread.Execute;
begin
  FreeOnTerminate := True;
  while not (Application.Terminated or Terminated) do
  begin
    FText := timetostr(now);
    Synchronize(DoPomazPanel);
    if not (Application.Terminated or Terminated)  then
      Sleep(FRepVal); //generalnie czekanie na samym końcu, i jeśli czekanie może być długie to dodatkowo przed sleep powinien być dodatkowy if
  end;
end;

generalnie działo się tak ponieważ kończyłeś aplikację, która kończyła wątek, tylko że wątek był już po sprawdzeniu warunku w while a przed wykonaniem 'mazania' po panelu, i kiedy kończył czekać i chciał pomazać to nie miał po czym bo panela już nie było i się wysypywał zamiast zakończyć

0

Witam,
Misiekd bardzo dziękuję za pomoc, jestem pod wrażeniem twojej wiedzy, jeśli mogę spytać ile lat poświęciłeś na zdobycie takiej wiedzy teoretycznej i zastosowania jej w praktyce ?
Pozdrawiam

0

tak ogólnie to gdzieś ponad 15 lat a w Delphi koło 6

0

Misiekd dzięki !

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.