2014-03-02 72 views
1

我试图做一个无限循环。但我希望循环每30秒运行一次。循环将开始。一堆if语句发生并且一些信息将被改变。那么循环必须暂停30秒,然后循环将再次开始。这必须不断地根据日期和时间“永远如何让delphi等待30sec然后继续

我正在寻找一种方式来暂停 30秒,然后循环继续下去。任何好的建议可以理解的,

程序将显示‘特殊’信息。随着时间改变信息的变化06:00 =数学; 07:30 =生物学,该程序还会显示你下一堂课开始前的时间,现在程序必须连续运行并更新程序的时间,以便你可以到底是什么时间段和多少时间直到下一个。

我想放一个“刷新”,以便脚本不会经常运行,吃你ram。th电子刷新率必须是30秒。

+2

问题不完整。 GUI应用程序或控制台应用程序?桌面或服务?主线程或工作线程?你需要能够取消吗?除非你提供这些细节,否则答案是睡眠。 –

+0

这将在后台运行。 VCL表单应用程序。暂停期间是不变的。唯一的原因是可以停止等待循环停止。 – GerhardAA

+1

在Interval设置为30000时使用定时器。每个定时器事件调用都是您的循环部分。所以你没有循环,只有一个方法,每n毫秒调用一次,直到你禁用定时器为止 –

回答

3

如果您有阻止GUI的代码,则可以使用后台线程和事件来提供非阻塞计时器。

创建一个新的Forms应用程序,并将TMemo组件放在窗体上。 本示例将在当前时间向您的TMemo添加一个新行。

主要形式有:

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. 

辅助线程:

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. 
8

根据您的更新,提供更多的细节,我想我会用一个单独的线程与定时器提供脉冲到驱动更新。

将计时器时间间隔设置为希望更新GUI的更新频率。例如,也许每分钟两次的刷新率就是你想要的,在这种情况下,将计时器间隔设置为30*1000

每当定时器启动时,使用当前系统时间计算出需要显示的信息,然后显示该信息。

请注意,此答案不会告诉您如何等待30秒并继续。但是,我怀疑这是解决实际问题的最简单解决方案。

您不想阻止您的程序,因为这会阻止用户界面响应。它会阻止你能够与UI进行交互并阻止UI自己绘制。在一个GUI程序中,你不能在主线程中阻塞。你应该只在后台线程中阻塞。但是线程增加了不必要的复杂性。你不想阻止。你不想等。你只需要一个常规脉冲来驱动更新。一个计时器。

相关问题