深入TEvent类并解决PulseEvent问题

问题来源于:

http://www.cnblogs.com/del/archive/2009/02/16/1391192.html

其中有一段代码:

procedure TForm1.Button5Click(Sender: TObject);

begin
  ShowMessage('TEvent 类没有提供这个功能'); {我试过用 PulseEvent(MyEvent.Handle) 也不行}
end;
 

作者只是说TEvent类没有这个功能或者直接使用PulseEvent也没有效果,但没有给出其他更多的解释。

在经过我一晚上艰苦卓绝(熬瞎眼)的努力下,现在终于把这个问题搞明白了。

首先,这个问题既不算Bug也不算问题,应该属于使用上和理论上的误区导致的。

简单点儿说,PulseEvent这个脉动事件实际上实在是太快了,它的状态转换时间远远少于TEvent.WaitFor的执行时间。也就是说在TEvent.WaitFor根本就没有响应过来(没明白是什么状况时)这个脉动事件已经结束了!!!!是不是有点拗口?好吧,直接上代码:

  while not Terminated do
  begin
    if WaitForSingleObject(FEvent.Handle, INFINITE) = WAIT_OBJECT_0 then
    //if FEvent.WaitFor(INFINITE) = wrSignaled then
    begin
      Synchronize(DoView);
      Sleep(1);
    end;

  end;

注意:上面的FEvent.WaitFor(INFINITE)语句在PulseEvent时永远不会触发,但是换成WindowsAPI:

WaitForSingleObject(FEvent.Handle, INFINITE) = WAIT_OBJECT_0

以API方式执行时却完全没有问题。

结论:只要在线程中使用WindowsApi方式进行事件等待即可解决问题。具体的调用方式就是你想怎么PulseEvent就怎么PulseEvent,完全不影响线程的正常运行。

一旦搞清楚了原理,那么很多事情就很好玩了,比如:

1.跨平台执行,很简单:

procedure TMnEvent.PulseEvent;
begin
{$IFDEF MSWINDOWS}
  Windows.PulseEvent(Handle);
{$ELSE}
  FEvent.SetEvent;
  FEvent.ResetEvent;
{$ENDIF}
end;

唯一一点需要注意的是:这种使用SetEvent和ResetEvent的方式绝对没有操作系统核心处理的精确,也就是说很难控制只执行一次。当然,如果你的系统要求不高,也可以在Windows上使用这种方式来执行,这种权衡就全部交给你自己控制吧。

2.将TEvent.WaitFor事件改为纯汇编方式执行???这个我不敢确认是否能够成功,也没有进行实验,因此只能交给有兴趣的同学去继续测试吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值