加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

windows – Delphi:没有冻结和处理消息的睡眠

发布时间:2020-12-14 02:14:53 所属栏目:Windows 来源:网络整理
导读:我需要一种暂停函数执行几秒钟的方法.我知道我可以使用sleep方法来执行此操作,但此方法会在执行时“冻结”应用程序.我也知道我可以使用类似下面的代码来避免冻结: // sleeps for 5 seconds without freezing for i := 1 to 5 do begin sleep(1000); applica
我需要一种暂停函数执行几秒钟的方法.我知道我可以使用sleep方法来执行此操作,但此方法会在执行时“冻结”应用程序.我也知道我可以使用类似下面的代码来避免冻结:

// sleeps for 5 seconds without freezing 
for i := 1 to 5 do
    begin
    sleep(1000);
    application.processmessages;
    end;

这种方法存在两个问题:一个是冻结仍然每一秒发生一次,第二个问题是每秒调用’application.processmessages’.我的应用程序是CPU密集型的,每个进程消息调用做了很多不必要的工作,使用不必要的CPU功率;我只想暂停工作流程,仅此而已.

我真正需要的是像TTimer一样暂停执行的方法,在下面的例子中:

// sleeps for 5 seconds
   mytimer.interval := 5000;
   mytimer.enabled := true;
   // wait the timer executes
   // then continue the flow
   // running myfunction
   myfunction;

这种方法的问题是’myfunction’不会等待mytimer,它会在mytimer启用后立即运行.

是否有其他方法可以实现我想要的停顿?

提前致谢.

解决方法

正如David所说,最好的选择是将工作转移到一个单独的线程中,并完全阻止主线程.但是,如果你必须阻塞主线程,那么至少你应该只在有等待处理的消息时调用ProcessMessages(),并让线程在剩下的时间内休眠.您可以使用MsgWaitForMultipleObjects()来处理它,例如:

var
  Start,Elapsed: DWORD;

// sleep for 5 seconds without freezing 
Start := GetTickCount;
Elapsed := 0;
repeat
  // (WAIT_OBJECT_0+nCount) is returned when a message is in the queue.
  // WAIT_TIMEOUT is returned when the timeout elapses.
  if MsgWaitForMultipleObjects(0,Pointer(nil)^,FALSE,5000-Elapsed,QS_ALLINPUT) <> WAIT_OBJECT_0 then Break;
  Application.ProcessMessages;
  Elapsed := GetTickCount - Start;
until Elapsed >= 5000;

或者:

var
  Ret: DWORD;
  WaitTime: TLargeInteger;
  Timer: THandle;

// sleep for 5 seconds without freezing 
Timer := CreateWaitableTimer(nil,TRUE,nil);
WaitTime := -50000000; // 5 seconds
SetWaitableTimer(Timer,WaitTime,nil,FALSE);
repeat
  // (WAIT_OBJECT_0+0) is returned when the timer is signaled.
  // (WAIT_OBJECT_0+1) is returned when a message is in the queue.
  Ret := MsgWaitForMultipleObjects(1,Timer,INFINITE,QS_ALLINPUT);
  if Ret <> (WAIT_OBJECT_0+1) then Break;
  Application.ProcessMessages;
until False;
if Ret <> WAIT_OBJECT_0 then
  CancelWaitableTimer(Timer);
CloseHandle(Timer);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读