问题
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.
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/22126082/how-to-make-delphi-wait-30sec-then-continue