Results 1 to 6 of 6

Thread: Eigen Stopwatch

  1. #1
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,230

    Eigen Stopwatch

    Voor een competitie programma moet er tijdens het starten van een ronde een 'timer' opgestart, die 15 minuten doorloopt. Hieronder staat de code, die ik heb gebruikt. De doelstelling is: een tijd laten lopen en toch interactie met het programma hebben. Nu mijn vragen:
    - Is dit de juiste manier?
    - zo ja, kan het nog worden verbeterd.
    - zo niet, wat is een andere/betere manier om het uit te voeren?
    Delphi Code:
    1. unit Unit1;
    2.  
    3. interface
    4.  
    5. uses
    6.   System.SysUtils, System.Variants, System.Classes,
    7.   Vcl.Controls, Vcl.Forms, Vcl.StdCtrls;
    8.  
    9. type
    10.  
    11.   TTimeProgressEvent = procedure(const aDisplayTime : TTime) of object;
    12.  
    13.   TMyStopwatch = class(TThread)
    14.   private
    15.     fStartTime : TTime;
    16.     fCalculatedTime   : TTime;
    17.     FOnProgress : TTimeProgressEvent;
    18.  
    19.      procedure DoProgress;
    20.     public
    21.       procedure execute; override;
    22.  
    23.       property OnProgress: TTimeProgressEvent read FOnProgress
    24.       write FOnProgress;
    25.  
    26.   end;
    27.  
    28.   TForm1 = class(TForm)
    29.     Label1: TLabel;
    30.     Button1: TButton;
    31.     Button2: TButton;
    32.     procedure Button1Click(Sender: TObject);
    33.     procedure Button2Click(Sender: TObject);
    34.   private
    35.     { Private declarations }
    36.     procedure displayTime(const aDisplayTime : TTime);
    37.   public
    38.     { Public declarations }
    39.     St : TMyStopwatch;
    40.   end;
    41.  
    42. var
    43.   Form1: TForm1;
    44.  
    45. implementation
    46.  
    47. {$R *.dfm}
    48.  
    49. procedure TForm1.Button1Click(Sender: TObject);
    50. begin
    51.   st := TMyStopwatch.Create(true);
    52.   st.fStartTime := now;
    53.   st.OnProgress := displayTime;
    54.   st.Start
    55. end;
    56.  
    57. procedure TForm1.Button2Click(Sender: TObject);
    58. begin
    59.   st.Terminate
    60. end;
    61.  
    62. procedure TForm1.displayTime(const aDisplayTime: TTime);
    63. begin
    64.   label1.Caption := Formatdatetime('nn:ss',aDisplayTime);
    65. end;
    66.  
    67. procedure TMyStopwatch.execute;
    68. var EndTime : TTime;
    69. begin
    70.   try
    71.   while not terminated do
    72.   begin
    73.     sleep(1000);
    74.     EndTime := now;
    75.     fCalculatedTime := EndTime - fStartTime;
    76.     Synchronize(DoProgress);
    77.   end;
    78.   finally
    79.     FreeOnTerminate := True;
    80.   end;
    81. end;
    82.  
    83. procedure TMyStopwatch.DoProgress;
    84. begin
    85.   if Assigned(FOnProgress) then
    86.     FOnProgress(fCalculatedTime);
    87. end;
    88.  
    89.  
    90. end.
    Delphi is great. Lazarus is more powerfull

  2. #2

  3. #3
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,230
    Die heb ik ook gezien maar los nooit het tussenstukje op van de start / stop. Door in een andere thread een sleep uit te voeren, heb ik geen problemen in de mainthread.
    Delphi is great. Lazarus is more powerfull

  4. #4
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,230
    In plaats van sleep kan ik ook TSimpleEvent gebruiken.
    Delphi is great. Lazarus is more powerfull

  5. #5
    Door Sleep(1000) te gebruiken kan je rare hiks krijgen in de update. Je klok zal iets trager verspringen dan die seconde, en uiteindelijk zal hij daardoor ineens een seconde overslaan.

    Ik heb ook weleens zo'n soort klokje gemaakt, overigens gewoon m.b.v. TTimer wat ook prima werkt in dit geval, maar in plaats van 1000 te gebruiken, berekende ik het aantal milliseconden tot de volgende hele seconde. De rest van je code kost tenslotte ook tijd, en op die manier kan je dat een beetje corrigeren.
    Ik zou dus het exacte tijdstip opslaan waarop je klop begint te lopen, en elke keer het interval berekenen t.o.v. die starttijd. Dan krijg je de meest soepele en precieze klok, die automatisch corrigeert voor het feit dat je niet de enige applicatie op je computer bent.

    De reden dat ik hier geen aparte thread voor zou maken, is omdat er (behalve de sleep) geen langdurige code is. Je wilt alleen een signaal na een opgegeven tijd: perfecte usecase voor de timer. Het van elkaar aftrekken van twee tijden is niet echt het zware werk waar je een thread voor nodig hebt.
    Last edited by GolezTrol; 08-May-18 at 12:18.
    1+1=b

  6. #6
    Paar kleine opmerkingetjes:

    • Ik zou de TMyStopwatch.Create overrullen en in de Create de FreeOnTerminate zetten. Op die manier hoef je de Suspended parameter ook niet mee te geven aan de Create (want die kun je dan in de inherited vast zetten). Want Suspended moet toch altijd true zijn omdat je fStartTime en OnProgress toe moet kennen. Ook kun je de try/finally dan in execute weghalen.
    • Ik zou st.fStartTime := now; ook in de Create zetten. Dan hoef je dat niet in je main-thread te doen (maar het is daar wel te overrulen indien nodig).
    • st.Start en st.Terminate hebben geen ; achter zich staan. Nu is dat niet nodig maar de andere ( end; ) hebben dat wel. Zorg dus voor uniformiteit.
    • Ik zie nu wel een probleem dat je Button2 kunt klikken voordat je Button1 klikt. Dan is St nog niet aangemaakt en krijg je een foutmelding. Tevens is het dat als je 2x op Button1 drukt dat de eerste St overschreven wordt en niet meer te bereiken is (dus niet meer te stoppen is). Ik weet niet of dat een probleem is in je voorbeeld.


    We hebben natuurlijk geen functionele omschrijving van dit project dus andere opmerkingen kan ik er niet over geven.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •