Autor Beitrag
ralfi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 153



BeitragVerfasst: Mi 16.07.03 17:47 
Hallo!
Kann man die enorme Systemauslastung durch TTimer irgendwie verhindern? Ich habe einige TTimer-Kompos in meiner Anwendung. Wenn die Timer gleichzeitig irgendwas machen, kann ich auf andere Komponenten auf de Form nicht zugreifen. Und die Systemauslastung-Indikator im Task-Manager ist weit über 80%. Kann man irgendwas machen?
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mi 16.07.03 17:53 
Es kommt noch schlimmer, zumindest bei mir. Lasse ich ein Modem und den entsprechenden Rechner länger laufen (Wochenende), so ist sogar das Datum verstellt, weil die Uhr anscheinend verlangsamt wird.

Würde mich auch interessieren, woran das liegt, bzw. was eine Alternative wäre.

_________________
Gruß
Hansa
recall
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 449



BeitragVerfasst: Mo 11.08.03 02:49 
@hansa: nenene die Uhr kann NICHT verlangsamt werden.
Die wird extern "vom BIOS" gesteuert.

Das kannst du einfach probieren: PC ausschalten, PC einschalten: Uhr ist noch gestellt ! (hehe)

Wenn deine Uhr langsamer wird, dann würde ich die BIOS-Batterie überprüfen, die kann alle oder alt sein :) .

Wie gross ist euer Interval vom Timer ?
Generell kommt die hohe Auslastung nicht vom Timer, sondern von der Art des Codes in OnTimer...

Nur Grafik z.B. kann auf Interval 1ms laufen (das macht nix) [jetzt kein DirectX o.ä. nur lineto usw]
Wohingegen jede Art von schreiben in visuelle Kompos enorm viel Rechenleistung braucht (ist aber wie gesagt nicht vom Timer abhängig).

@ralfi: Nimm nicht mehrere Timer-Kompos, sondern nur eine :)
Du kannst ja das kleinste Interval schalten und dann mit einer globalen Variablen... usw.

Achso: Ich hatte das Problem bei einem meiner Programme auch. Bin aber nicht drumherum gekommen, die Prozeduren zu "splitten".

Viele Grüsse.
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mo 11.08.03 10:31 
recall hat folgendes geschrieben:
Das kannst du einfach probieren: PC ausschalten, PC einschalten: Uhr ist noch gestellt ! (hehe)


Das ist wohl klar, aber falls die Batterie leer wäre, so wären auch alle anderen Bios-Einstellungen futsch. Das BIOS geht wohl kaum hin und sagt sich, bei schlechter werdender Batterie, erst mal die Uhrzeit zu verlangsamen, dann das Datum und wenn noch weniger Saft drauf ist, dann mal den Festplattentyp umzustellen. :P

Das Phänomen ist wirklich so : Modem läuft über Nacht, natürlich mit meinem Programm im Hintergrund, was eben entsprechende Anrufe annimmt und die Daten verarbeitet. Hat dieses Programm nun nichts zu tun und es läuft sagen wir mal 3-4 Tage ohne Aktivität, dann steht die Uhr später morgens um 8 noch auf z.B. 23:30 des Vortages.

Das ganze fiel erst durch zwei sehr lange Wochenenden auf.

_________________
Gruß
Hansa
MSCH
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1448
Erhaltene Danke: 3

W7 64
XE2, SQL, DevExpress, DevArt, Oracle, SQLServer
BeitragVerfasst: Mo 11.08.03 11:20 
lösche den Timer (ist eh grütze) und schreibe das in Threads, was der Timer macht bzw. machen sollte. So hast mehr Resourcen frei - allerdings etwas aufwändiger zu proggen.

grez
msch
Tryer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 226
Erhaltene Danke: 7



BeitragVerfasst: Mo 11.08.03 15:33 
Ich hab eben mal nen Thread geschrieben der eine "beliebige" Anzahl an Events auslösen kann, wobei das Intervall natürlich nicht zu kurz werden sollte. Die Prozessorauslastung hält sich (genauso wie natürlich die Genauigkeit bei sehr kleinen Intervallen ;) ) in Grenzen.
Je nach Anwendungsfall läßt sich die Priorität sicherlich noch senken.

ausblenden volle Höhe Delphi-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:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
unit TimerThread;

interface

uses
  classes, windows;

type
  TTimerInterval = 10..High(LongWord);

  PTimerItem = ^TTimerItem;
  TTimerItem = record
    Method: TNotifyEvent;
    Interval: TTimerInterval;
    Periodic: Boolean;
    Start: Int64;
  end;

  TTimerThread = class(TThread)
  private
    FList: TThreadList;
    FActEvent: TNotifyEvent;
  protected
    procedure Execute; override;
    procedure DoTimeEvent;
  public
    constructor Init;
    destructor Destroy; override;
    procedure StartTimer(Event: TNotifyEvent; Interval: TTimerInterval; Periodic: Boolean);
    procedure StopTimer(Event: TNotifyEvent);
  end;

implementation

procedure TTimerThread.DoTimeEvent;
begin
  FActEvent(Self);
end;

procedure TTimerThread.Execute;
var
  i: Integer;
  Time: LongWord;
begin
  while not Terminated do
  begin
    Sleep(1);
    i := 0;
    with FList.LockList do
      try
        while i < Count do begin
          if PTimerItem(Items[i]) <> nil then
          begin
            with PTimerItem(Items[i])^ do
            begin
              Time := GetTickCount;
              if Time < Start then Dec(Start, High(LongWord)); //Überlauf abfangen
              if (Time - Start) >= Interval then
              begin
                if Periodic then
                  Start := Time // nächstes Intervall vorbereiten
                else
                  StopTimer(Method);
                { Methode ausführen :}
                FActEvent := PTimerItem(Items[i])^.Method;
                Synchronize(DoTimeEvent);
              end;  { if (Time - Start).. }
            end;  { with PTimerItem(Items[i])^.. }
          end;  { if PTimerItem(Items[i]) <> nil }
          Inc(i);
        end{ while i < Count }
      finally
        FList.UnlockList;
      end;
  end{ while not Terminated }
end;

procedure TTimerThread.StartTimer(Event: TNotifyEvent; Interval: TTimerInterval;
  Periodic: Boolean);
var
  p: PTimerItem;
begin
  New(p);
  p^.Method := Event;
  p^.Interval := Interval;
  p^.Periodic := Periodic;
  FList.Add(p);
  p^.Start := GetTickCount;

  if Suspended then Resume;
end;

procedure TTimerThread.StopTimer(Event: TNotifyEvent);
var
  i:Integer;
  p: PTimerItem;
begin
  with FList.LockList do
    try
      for i := Pred(Count) downto 0 do
      begin
        if (@PTimerItem(Items[i])^.Method = @Event) then
        begin
          p := Items[i];
          Items[i] := nil;
          Dispose(p);
          Delete(i);
          Break;
        end;
      end;
      if Count = 0 then Suspend;
    finally
      FList.UnlockList;
    end;
end;

constructor TTimerThread.Init;
begin
  inherited Create(False);
  FList := TThreadList.Create;
  Priority := tpTimeCritical; // möglich durch Sleep(1) im Execute
end;

destructor TTimerThread.Destroy;
var
  i: Integer;
  p: PTimerItem;
begin
  Terminate;
  WaitFor;
  with FList.LockList do
  try
    for i := Pred(Count) downto 0 do
    begin
      p := Items[i];
      Items[i] := nil;
      Dispose(p);
    end;
  finally
    FList.UnlockList;
  end;
  FList.Free;
  inherited;
end;

end.

Beispielaufruf:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var Timers: TTimerThread;
...
//FormCreate:
  Timers := TTimerThread.Init;
  Timers.StartTimer(Button1Click, 1000, False);
  Timers.StartTimer(Button2Click, 200, True);
...
//FormClose:
  Timers.Free;
Hier wird dann alle 200ms "Button2Click" aufgerufen und einmal nach 1s "Button1Click".

MfG,
Tryer
recall
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 449



BeitragVerfasst: Mo 11.08.03 21:40 
@hansa:

Das wäre aber Blödsinn (mit der langsameren Uhr), wenn Windows die Zeit noch "berechnen" würde...

Hmmm... kann ich mir nicht erklären.
Achso, hatte eine faste leere BIOS-Batterie, erst murkste das Datum, dann erst der Rest (nur die Uhr lief fast bis zum Schluss) :D

Viele Grüsse.
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mo 11.08.03 23:45 
recall hat folgendes geschrieben:
... wenn Windows die Zeit noch "berechnen" würde...
Hmmm... kann ich mir nicht erklären...


Tja, das ist aber seit 5 Jahren Fakt. Wer berechnet denn die Uhr, wenn nicht Windows :?:

_________________
Gruß
Hansa
recall
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 449



BeitragVerfasst: Di 12.08.03 14:57 
Zitat:
Tja, das ist aber seit 5 Jahren Fakt. Wer berechnet denn die Uhr, wenn nicht Windows ?

=> BIOS !
Beim starten liest Windows ja die BIOS-Uhr aus. Wieso sollte es das nicht dauernd machen, anstatt wertvolle Rechenressourcen in die Berechnung zu stecken ?

Aber OK: Nehmen wir an, dass Windows die BIOS-Uhr beim Start ausliest.
Ab jetzt berechnet es die Zeit selbstständig.
Wenn eine Sekunde sich aus der Prozessor-Taktung berechnen würde, wie sollte dann die Uhr jemals nach gehen ? Selbst bei Vollauslastung bleibt der Takt der selbe :!: :?:

Viele Grüsse.