Avatar billede aasuper Nybegynder
05. oktober 2000 - 19:56 Der er 15 kommentarer og
1 løsning

Hvordan laves en pause?

Hej

Jeg har i et program brug for, at der skal være en pause på et bestemt antal sekunder, før programmet kører videre.
Man kan selvfølgelig bruge timeren, men der må være en bedre måde.

Hvordan kan det laves?


>>AASuper
Avatar billede rfogh Nybegynder
05. oktober 2000 - 20:10 #1
Sleep(500)  pause på 500 millisekunder...
Avatar billede dj Nybegynder
05. oktober 2000 - 20:37 #2
Da sleep har det med at lukke lidt for meget af for alting kan du også vælge en anden og lidt mere fleksibel løsning der også tillader at du kan bruge den til at aktivere noget et bestemt antal gange og på bestemte tidspunkter, og så er den langt mere præcis end en Ttimer der er MEGET upræcis i sin optælling.

var
  tid: Integer;
begin
  DoSomething;
  //Lav en pause her
  tid:=Gettickcount;
  repeat
    application.processmessages;
    case gettickcount-tid of
      0: label1.caption:=\'Pausen er påbegyndt!\';
      1000: label1.caption:=\'Der er nu gået 1 sekund!\';
      2000: label1.caption:=\'Der er nu gået 2 sekunder!\';
      3000: label1.caption:=\'Der er nu gået 3 sekunder!\';
      4000: label1.caption:=\'Der er nu gået 4 sekunder!\';
      5000: label1.caption:=\'Der er nu gået 5 sekunder!\';
    end;
  until gettickcount-tid > 5000;
  //fortsæt med resten af koden her
  showmessage(\'JEG ER FÆÆÆRDIG!\');
end;

:)

Mvh. _DJ_

PS. Prøv ovenstående, jeg kan ikke give dig yderligere hjælp før om 1 uge da jeg er på vej til London.
Avatar billede borrisholt Novice
06. oktober 2000 - 08:25 #3
Problemet med DJ løsning er blot at den bruger buissy waiting, altså brænder CPU tid af indtil at tiden er gået. Det har den udlæmpeat det låser hel dit operativ system. I stedet skal du bruge en SleepEx() funktion, den er mere nøjagtig end Sleep() er. endnu bederekan du kaste dig over Tråd programmering.

Jens B
Avatar billede dj Nybegynder
06. oktober 2000 - 08:46 #4
Borrisholt>>

Nej, min låser ikke operativsystemet, læg venligst mærke til denne linje i koden der forhindrer dette:

application.processmessages;

absolut sidste bemærkning før jeg er taget til London .. ses

:)

Mvh. _DJ_
Avatar billede borrisholt Novice
06. oktober 2000 - 08:50 #5
DJ >> application.processmessages;  Ok den havde jeg lige overset ... Men anyway at brænde CPU tid af bare for at holde en pause .. det giver ikke mening ...

Istedet er der emner som EventStyret programmering, (tråd baseret)Timere, og tråde !

Jens B
Avatar billede lrj Nybegynder
07. oktober 2000 - 16:02 #6
application.processmessages - mange ved åbenbart ikke hvad denne sætning gør. Det betyder, at skulle der være events som endnu ikke er behandlet af programmet (musen har klikket på en knap eller bare bevæget sig inden for programmets form) bliver de behandlet. Det vil også sige, at man kan resikere at kode bliver udført indeni sig selv (fx. hvis man laver en application.processmessages indeni en onClick event. Dette kan give nogle meeega nasty fejl, som er ret svære at finde.

Håber det afmystificerede det lidt.

Og jo, det *er* busy waiting.
Avatar billede aasuper Nybegynder
07. oktober 2000 - 17:06 #7
Når løsningen, hvor application.processmessages indgår ikke er den bedste, hvordan laves en trådbaseret timer så?


>>AASuper
Avatar billede lrj Nybegynder
07. oktober 2000 - 18:04 #8
application.processmessages er okay hvis du ved hvad det betyder og tager højde for det. Men normalt er det ikke nødvendigt at bruge den hvis du ikke har lavet noget *meget* speciel kode..
Avatar billede borrisholt Novice
09. oktober 2000 - 08:28 #9
lrj>>Sev om du laver en løkke med Application.ProcessMessages belaster det aligevel dit OS ganske uhensigts messigt. Men som du selv siger så \"application.processmessages - mange ved åbenbart ikke hvad denne sætning gør\".

Jeg bruger den kun selv yderst sjældent. I stedet bruger jeg tråde og messages til at styre flowet i mine programmer.


aasuper>> Her er i hvertfald en løsning på en trådbaseret Timer. Det er et komponent, og skal instaleres som så :

unit ThdTimer;

interface

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

const
  DEFAULT_INTERVAL = 1000;

type
  TThreadedTimer = class;

  TTimerThread = class(TThread)
  private
    FOwner: TThreadedTimer;
    FInterval: Integer;
    FStop: THandle;
  protected
    constructor Create(CreateSuspended: Boolean); virtual;
    procedure Execute; override;
  end;

  TThreadedTimer = class(TComponent)
  private
    FEnabled: Boolean;
    FOnTimer: TNotifyEvent;
    FTimerThread: TTimerThread;

    procedure DoTimer;

    procedure SetEnabled(Value: Boolean);
    function GetInterval: Integer;
    procedure SetInterval(Value: Integer);
    function GetThreadPriority: TThreadPriority;
    procedure SetThreadPriority(Value: TThreadPriority);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

  published
    property Enabled: Boolean read FEnabled write SetEnabled;
    property Interval: Integer read GetInterval write SetInterval
      default DEFAULT_INTERVAL;
    property OnTimer: TNotifyEvent read FOnTimer write FOnTimer;
    property ThreadPriority: TThreadPriority read GetThreadPriority
      write SetThreadPriority;
  end;

procedure Register;

implementation

{ TTimerThread }

constructor TTimerThread.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);

  // create event object for signaling interruptions
  FStop := CreateEvent(nil, False, False, nil);
end;

procedure TTimerThread.Execute;
begin
  repeat
      // wait for time elapse
      if WaitForSingleObject(FStop, FInterval) = WAIT_TIMEOUT then
        // if time elapsed run user-event
        Synchronize(FOwner.DoTimer);
  until Terminated;

  // Delete event object
  CloseHandle(FStop);
end;

{ TThreadedTimer }

constructor TThreadedTimer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  // create timer thread
  FTimerThread := TTimerThread.Create(True);
  FTimerThread.FOwner := Self;
  FTimerThread.FreeOnTerminate := False;
  FTimerThread.Priority := tpNormal;
  FTimerThread.FInterval := DEFAULT_INTERVAL;
end;

destructor TThreadedTimer.Destroy;
begin
  // Destroy thread
  // signal thread to terminate
  FTimerThread.Terminate;
  SetEvent(FTimerThread.FStop);
  // resume if stopped
  if FTimerThread.Suspended then FTimerThread.Resume;
  // wait and free
  FTimerThread.WaitFor;
  FTimerThread.Free;

  inherited Destroy;
end;

procedure TThreadedTimer.DoTimer;
begin
  if Assigned(FOnTimer) then
    FOnTimer(self);
end;

procedure TThreadedTimer.SetEnabled(Value: Boolean);
begin
  if Value <> FEnabled then
  begin
    FEnabled := Value;

    if FEnabled then
    begin
      // When enabled resume thread
      if FTimerThread.FInterval > 0 then
      begin
        SetEvent(FTimerThread.FStop);
        FTimerThread.Resume;
      end;
    end
    else
      // suspend thread
      FTimerThread.Suspend;
  end;
end;

function TThreadedTimer.GetInterval: Integer;
begin
  Result := FTimerThread.FInterval;
end;

procedure TThreadedTimer.SetInterval(Value: Integer);
begin
  if Value <> FTimerThread.FInterval then
  begin
    Enabled := False;
    FTimerThread.FInterval := Value;
  end;
end;

function TThreadedTimer.GetThreadPriority: TThreadPriority;
begin
  Result := FTimerThread.Priority;
end;

procedure TThreadedTimer.SetThreadPriority(Value: TThreadPriority);
begin
  FTimerThread.Priority := Value;
end;

procedure Register;
begin
  RegisterComponents(\'System\', [TThreadedTimer]);
end;

end.


Jens B

Avatar billede lrj Nybegynder
09. oktober 2000 - 08:57 #10
Jeg bemærkede også at det er busy waiting - men hvis det er korrekt brugt i forb. med en lang databehandling, så er det jo okay. Der er bare smartere måder at gøre tingene på - fx. med tråde :=)
Avatar billede borrisholt Novice
09. oktober 2000 - 09:02 #11
Den der med busy waiting har ejg aldrig rigtig forståer hvorfor og hvordan ... når nu man kan bruge events, hvad skal man så med det andet ?
Avatar billede aasuper Nybegynder
09. oktober 2000 - 15:06 #12
-Tak for hjælpen.


>>AASuper
Avatar billede lrj Nybegynder
09. oktober 2000 - 15:14 #13
borrisholt - når man starter med at programmere er asynkron programmering temmelig svær at fatte. MEGET svær, faktisk. Og så er det trælst hvis programmet holder op med at \"svare\" når det fx. laver en lang beregning. Men jeg er rørende enig - busy waiting er fjollet :=)
Avatar billede phansen Nybegynder
13. november 2000 - 17:19 #14
borrisholt> Humn, lige hurtigt..

Hvad betyder F\'erne i Fblahblah... (FEnabled etc.)?
Hvad sker der hvis man fra component\'en skriver til trådens FInterval, samtidig med at tråden læser selv samme FInterval? (for at smide den efter WaitForSingleObject el. lign.)..
Avatar billede borrisholt Novice
14. november 2000 - 08:45 #15
pHansen > Fblabla, er simpelthen et udtryk for en konvention omkring navngivning .... Jeg mener det med at sætte er F foran private datamedlemmer er en del af den ungarske notation... Dog er jeg ikke helt sikker på dette .... Men mange mennesker bruger det at sætte et F foran private datamedlemmer ... Det giver en fordel nåe dine properties skal navngives ...

Jens B
Avatar billede lrj Nybegynder
14. november 2000 - 11:15 #16
Og det er rigtigt smart, hvis man skriver følgende i sin klasse:

property whatnot:integer;

og laver en masse andre. Trykker du så Ctrl+shift+c laver den selv dine variable i private sektionen (med F foran), laver en set metode, og udfylder kroppen...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester