Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Dinge zeitversetzt in einer Schleife ausführen lassen


delphibenutzer - Do 26.11.09 14:44
Titel: Dinge zeitversetzt in einer Schleife ausführen lassen
Hi!

Ich möchte, dass in meinem Beispielprogramm das Label 10 mal nacheinander eine höhere Zahl ausgibt. Wie ein Countdown blos umgekehrt. Dazu habe ich folgenden Code geschrieben:


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:
unit beispiel;

interface

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

type
  TForm4 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form4: TForm4;
  i,j: integer;

implementation

{$R *.dfm}

procedure TForm4.Button1Click(Sender: TObject); {
var i,j : integer;             }

begin

for i := 0 to  10 do
begin
  j := j + i;
  sleep(50);
end;



end;

procedure TForm4.Timer1Timer(Sender: TObject);
begin
label1.Caption := IntToStr(i);
end;

end.



Nun wartet das Programm dann aber eine ganze Weile am Stück, und gibt dann schon die letzte Zahl aus. Kann mir jemand erklären, was ich falsch gemacht habe?

Moderiert von user profile iconGausi: Delphi-Tags hinzugefügt


platzwart - Do 26.11.09 15:03

Bei dir sollte zumindest eine Warnung kommen, dass man globale Variablen nicht als Schleifenzähler verwenden sollte!

Besser gehst du folgendermaßen vor:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var
 counter: Integer
[...]
counter:= 10;
[...]
procedure TForm4.Timer1Timer(Sender: TObject);
begin
 Label1.Caption := IntToStr(counter);
 Counter:= Counter - 1;
 If(Counter < 0)then
  Timer1.Enabled:= False;
end;


Das Problem an deiner Konstruktion: Das Sleep friert dein komplettes Programm ein. Die Timermethode wird nicht parallel zu deiner Schleife abgearbeitet.


Critter - Do 26.11.09 15:31

Hi,

das Problem ist, das deine Anwendung wenn sie schläft nichts mach und wenn sie etwas macht (also Zählt) keine Zeit hat das Fenster neu zu zeichnen. Das ganze sollte sich so aber leicht beheben lassen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
for i := 0 to  10 do
begin
  j := j + i;
  Application.ProcessMessages;
  sleep(50);
end;


critter


thepaine91 - Do 26.11.09 15:38

Sowas ist mit Timer besser als die Anwendung einzufrieren mit sleep() daher Timer nehmen. Intervall kann dann sleep ersetzen usw...


Critter - Do 26.11.09 16:14

Hi,
user profile iconthepaine91 hat folgendes geschrieben Zum zitierten Posting springen:
Sowas ist mit Timer besser als die Anwendung einzufrieren mit sleep() daher Timer nehmen. Intervall kann dann sleep ersetzen usw...


Sowas ist mit Threads besser als mit Timern ;).
Die Frage ist doch was seine Ansprüche sind. Wenn er seinen bisherigen Ansatz verstanden halte ich es für Sinnvoll ihn diesen Weg erst mal weiter gehen zu lassen wenn er dann auf weitere Probleme wie z.B. "Meine Anwendung lässt sich nicht mehr bedienen" stößt wird er schon wieder nachfragen. Ob er es dann mit einer Zeitterminierten Schleife ohne Sleep, unter Verwendung von Tickcount, Timern oder Threads löst ist egal. Wichtig ist, dass er einen Weg findet, den er auch versteht.

Verstehe mich nicht Falsch, ich finde den Hinweis auf Timer gut und wahrscheinlich würde ich bei dieser Problematik auch auf diese zurück greifen, aber sie sind bei weiten nicht die einzige Lösung und ich würde nicht pauschal behaupten, dass Lösung X besser ist als Lösung Y. Das kommt immer auf das Problem und die Kenntnisse des jeweiligen Programmierers an.

critter


platzwart - Do 26.11.09 16:36

user profile iconCritter hat folgendes geschrieben Zum zitierten Posting springen:
Hi,
Sowas ist mit Threads besser als mit Timern ;).
[...] und ich würde nicht pauschal behaupten, dass Lösung X besser ist als Lösung Y. Das kommt immer auf das Problem und die Kenntnisse des jeweiligen Programmierers an.
critter


Ehm... lol... fällt dir was auf? Threads hier anzuwenden wäre a) viiiiiiel zu kompliziert, b) total übertrieben, c) relativ schwierig zu verstehen. Daher sind Timer hier an dieser Stelle für diesen User das absolut beste Mittel der Wahl ;)


thepaine91 - Do 26.11.09 16:40

Naja 1. brauch man für einen Timer wirklich nicht sehr viele Kenntnisse.
2. Und für sowas einen Thread zu verwenden sehe ich auch eher als "Schwachsinn" an.
3. Verwendet er sowieso schon einen Timer nur ist die Aufgabe des Timers noch nicht ganz Perfekt.

Abgesehen von seinem können würde auch ich es nicht in einem Thread machen. Es wäre viel zu aufwendig für so eine einfache Aufgabe.


Critter - Do 26.11.09 18:40

Hi,
user profile iconplatzwart hat folgendes geschrieben Zum zitierten Posting springen:
Ehm... lol... fällt dir was auf? Threads hier anzuwenden wäre a) viiiiiiel zu kompliziert, b) total übertrieben, c) relativ schwierig zu verstehen. Daher sind Timer hier an dieser Stelle für diesen User das absolut beste Mittel der Wahl ;)

Fällt dir der ";)" in dem Satz auf? Ich wollte user profile icondelphibenutzer auf keinen Fall Threads vorschlagen die währen bei der komplexen Berechnung und der nötigen Syncronisation für die Ausgabe an dieser Stelle nicht sinnvoll. Ich wollte lediglich user profile iconthepaine91s Pauschale aussage ein wenig Karikieren. Wie gesagt es geht mir hier nicht darum gegen Timer zu Wettern, sondern nur vor zu pauschalen Aussagen zu warnen.
Ich gestehe aber ein, dass sie beim zweiten lesen weit weniger pauschel ist als ich sie beim ersten lesen wahr genommen habe.

user profile iconthepaine91 hat folgendes geschrieben Zum zitierten Posting springen:
3. Verwendet er sowieso schon einen Timer nur ist die Aufgabe des Timers noch nicht ganz Perfekt.

Ah, das war mir nicht aufgefallen, ich habe nur die Schlafende Schleife beachtet. Da der Programmierer scheinbar diese Variante entwickelt hat schien es mir richtig ihn auf diesem Weg weiter gehen zu lassen. Aber du hast natürlich recht, da er sich auch an Timern versucht hat, ist es sogar notwendig in auf den richtigen Einsatz dieser hin zu weisen. Wenn er es nicht hätte, dann währe es auch Ok gewesen, ich habe mich nur ein wenig an der Absolutheit die ich aus deiner Aussage las gestoßen, denn wie immer gibt es auch hier mehrere absolut gangbare Lösungen.

critter