Autor Beitrag
CenBells
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1547

Win 7
Delphi XE5 Pro
BeitragVerfasst: Di 08.04.03 21:01 
Hallo leute,

ich habe nen timer in nen Thread ausgelagert, um unabhängig von eventuell rechenintensiven prozeduren immer die aktuelle zeit in der anwendung angezeigt zu bekommen.

Folgendermaßen sieht die implementierung aus

ausblenden volle Höhe 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:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
type
  TCBThreadTimer = class(TThread)
  private
    FTimer: TTimer;
    FSeconds, FMinutes, FHour: Integer;
    FTimerSecondsWereNulled: Boolean;
    FSynchronizeEvent: TNotifyEvent;
    procedure OnThreadTimer(ASender: TObject);
    procedure SynchronizeDisplayWithApp;
  public
    destructor destroy; override;
    constructor create(ASecond, AMinute, AHour: Integer);overload;
    procedure execute; override;
    procedure cbKillTimer;
    property Minute: Integer read FMinutes;
    property Hour: Integer read FHour;
    property SynchronizeEvent: TNotifyEvent read FSynchronizeEvent write FSynchronizeEvent;
  end;

implementation

uses SysUtils;

{ TCBThreadTimer }


//------------------------------------------------------------------------------
procedure TCBThreadTimer.cbKillTimer;
begin
  while not terminated do
    Terminate;
end;


//------------------------------------------------------------------------------
constructor TCBThreadTimer.create(ASecond, AMinute, AHour: Integer);
begin
  FSeconds := ASecond;
  FMinutes := AMinute;
  FHour := AHour;
  FTimer := TTimer.Create(nil);
  FTimer.Interval := 60000 - (ASecond * 1000);
  FTimer.Enabled := false;
  FTimer.OnTimer := OnThreadTimer;
  FTimerSecondsWereNulled := false;   
  FreeOnTerminate := true;
  inherited create(TRUE);
end;


//------------------------------------------------------------------------------
destructor TCBThreadTimer.destroy;
begin
  FTimer.OnTimer := nil;
  FreeAndNil(FTimer);
  inherited;
end;


//------------------------------------------------------------------------------
procedure TCBThreadTimer.execute;
begin
  resume;
  FTimer.Enabled := true;
  inherited;
end;


//------------------------------------------------------------------------------
procedure TCBThreadTimer.OnThreadTimer(ASender: TObject);
begin
  if not FTimerSecondsWereNulled then begin
    FTimer.Interval := 60000;
    FTimerSecondsWereNulled := true;
  end;
  inc(FMinutes);
  if FMinutes = 60 then begin
    FMinutes := 0;
    inc(FHour);
  end;
  if FHour = 24 then
    FHour := 0;
if assigned(FSynchronizeEvent) then
  Synchronize(SynchronizeDisplayWithApp);
end;


//------------------------------------------------------------------------------
procedure TCBThreadTimer.SynchronizeDisplayWithApp;
begin
  FSynchronizeEvent(Self);
end;


ich erzeuge den thread so:
ausblenden Quelltext
1:
2:
3:
  FThreadTimer := TCBThreadTimer.create(LSecond, LMinute, LHour);
  FThreadTimer.SynchronizeEvent := SetTimeToDisplay;
  FThreadTimer.execute;


SetTimeToDisplay sieht so aus
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.SetTimeToDisplay(ASender: TObject);
var
  LMinString, LHourString: String;
begin
  if FThreadTimer.Minute < 10 then
    LMinString := '0';
  LMinString := LMinString + IntToStr(FThreadTimer.Minute);
  if FThreadTimer.Hour < 10 then
    LHourString := '0';
  LHourString := LHourString + IntToStr(FThreadTimer.Hour);

  vSBar.Panels[2].Text := 'Serveruhrzeit: ' + LHourString + ':' + LMinString;
end;


Kann mir wer sagen, was daran falsch läuft?
Gruß
KEn
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Di 08.04.03 21:39 
Was ich dir sagen kann ist, dass die TTimer Komponente eine Botschaft für das Timer-Ereignis verwendet und diese wird, da du keine Botschaftsschleife für diesen Thread eingerichtet hast, vom Hauptthread abgearbeitet. Womit die Thread-Funktion dahin ist. Nutze lieber eine Schleife in der du Sleep(Interval) aufrufst und danach aktualisierst.

_________________
Ist Zeit wirklich Geld?
CenBells Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1547

Win 7
Delphi XE5 Pro
BeitragVerfasst: Di 08.04.03 22:01 
und wie müsste dann die schleife aussehen?
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Mi 09.04.03 06:22 
Ist mir gerade aufgefallen:
Zitat:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
procedure TCBThreadTimer.Execute; 
begin 
  resume;   { <-- Execute wird nur ausgeführt, wenn der Thread bereits läuft, also ist diese Zeile unsinnig }
  FTimer.Enabled := true; 
  inherited; { <-- und was soll TThread.Execute bringen? Diese Funktion ist leer, also kannst du diesen Aufruf weg lassen. Zudem beendet sich dein Thread sofort nach dem Start, da du keine "Endlos"-Schleife eingebaut hast.
end;



Das habe ich zwar schon in meinem Text geschrieben, aber hier der Quellcode:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TCBThreadTimer.Execute; 
begin 
  while (not Terminated) and (not Application.Terminated) do
  begin
    Sleep(FInterval);
    Synchronize(TimerEvent);
  end;
end;

_________________
Ist Zeit wirklich Geld?
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mi 09.04.03 06:52 
@AndyB: soviel ich weiß erstellt ein TThread-Objekt intern ein eigenes Fenster für Botschaftsbehandlungen, hat also eine eigene Message-Queue

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
CenBells Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1547

Win 7
Delphi XE5 Pro
BeitragVerfasst: Mi 09.04.03 08:48 
@AndyB: Danke für den Code. Das war aber nicht das, was ich meinte

Zitat:
Was ich dir sagen kann ist, dass die TTimer Komponente eine Botschaft für das Timer-Ereignis verwendet und diese wird, da du keine Botschaftsschleife für diesen Thread eingerichtet hast, vom Hauptthread abgearbeitet


Aber nichts destotrotz habe ich jetzt meinen Thread umgestellt und mache es nur mit sleep. Das war auch nicht di schwierigkeit. Interessant wäre nur die messagebehandlungsroutine für den timer im thread.
Geht auch ohne ganz herrvorragend. :D

Gruß
Ken