Question

I am trying to make an infinite loop but I want the loop to run every 30 seconds. The loop will start. A bunch of if statements take place and some information will be changed. The loop must then pause for 30 seconds and then the loop will start again. This must continue forever.

I am looking for a way to pause the loop for 30 seconds and then continue. Any good advice will be appreciated.

EDIT #1

The program shows "special" information based on date and time: As the time changes the information changes: 06:00 = math; 07:30 = biology. The program also shows you the time left until the next class starts. Thus the program needs to run continuously to update the time so that it knows exactly what period it is and how much time is left until the next period.

EDIT #2

I want put in a "refresh" so that script I want the script to be called on a set interval so that it is not running constantly and eating the ram. This interval must be 30 seconds.

Était-ce utile?

La solution 2

If you have code that blocks the GUI, you can use a background thread and an event to provide a non blocking timer.

Create a new Forms application and put a TMemo component on your form. This example will add a new line with the current time to your TMemo.

Main form:

unit u_frm_main;

interface

uses
  u_workthread,
  SysUtils,
  Windows,
  Forms,
  SyncObjs, Classes, Controls, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    Worker : TWorkThread;
    procedure ShowData;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ShowData;
begin
 // do whatever you need to do here... 
 // show current time in memo
 Memo1.Lines.Add(FormatDateTime('HH:NN:SS', Now));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 // create our worker thread and start it
 Worker := TWorkThread.Create(3, ShowData);
 Worker.Start;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 // signal our worker thread that we are done here
 Worker.ThreadEvent.SetEvent;
 // terminate and wait
 Worker.Terminate;
 Worker.WaitFor;
end;

end.

Worker Thread:

unit u_workthread;

interface

uses
  SysUtils,
  SyncObjs,
  Classes;

type
  TWorkProc = procedure of object;

  TWorkThread = class(TThread)
  private
    { Private declarations }
    Counter   : Integer;
    FTimeout  : Integer;
    FEventProc: TWorkProc;
    procedure DoWork;
  protected
    procedure Execute; override;
  public
    ThreadEvent : TEvent;
    constructor Create(TimeoutSeconds : Integer; EventProc: TWorkProc ); // timeout in seconds
    destructor Destroy; override;
  end;

implementation

procedure TWorkThread.DoWork;
begin
 // put your GUI blocking code in here. Make sure you never call GUI elements from this procedure
 //DoSomeLongCalculation();
end;

procedure TWorkThread.Execute;
begin
 Counter := 0;
 while not Terminated do
  begin
   if ThreadEvent.WaitFor(FTimeout) = wrTimeout then
    begin 
     DoWork;
     // now inform our main Thread that we have data
     Synchronize(FEventProc);
    end;
   else
    // ThreadEvent has been signaled, exit our loop
    Break;
  end;
end;

constructor TWorkThread.Create(TimeoutSeconds : Integer; EventProc: TWorkProc);
begin
 ThreadEvent := TEvent.Create(nil, True, False, '');
 // Convert to milliseconds
 FTimeout := TimeoutSeconds * 1000;
 FEventProc:= EventProc;
 // call inherited constructor with CreateSuspended as True
 inherited Create(True);
end;

destructor TWorkThread.Destroy;
begin
 ThreadEvent.Free;
 inherited;
end;


end.

Autres conseils

Based on your update that provides more details I think I would use a single thread with a timer to provide a pulse to drive updates.

Set the timer interval to be whatever rate you wish updates to the GUI to occur at. For instance, perhaps a refresh rate of twice a minute is what you want, in which case set the timer interval to 30*1000.

Whenever the timer fires, use the current system time to work out the information that you need to display, and then display that information.

Note that this answer does not tell you how to wait 30 seconds and continue. However, I suspect that this is the easiest solution to your actual problem.

You don't want to block your program because that would stop the UI being responsive. It would stop you being able to interact with the UI and stop the UI from being able to paint itself. In a GUI program you must not block in the main thread. You should only block in background threads. But threads add complexity that is just needless. You don't want to block. You don't want to wait. You just need a regular pulse to drive updates. A timer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top