循环阻止事件触发

时间:2018-07-26 19:59:53

标签: loops delphi events

此代码是针对另一个问题建议的解决方案。 当我尝试运行它时,我的代码中的事件没有触发。
循环阻止事件触发。

关于如何避免此问题并允许事件触发的任何建议? 如果删除循环,则事件将按预期触发。 在继续之前,我需要确保事件触发(或超时)。 有什么建议吗?

谢谢。

uses
 ..., DateUtils, SyncObjs;

type
  MyClass = class
  private
    doneEvent: TEvent;
    procedure COMEventHandler(parameters);
    procedure Loop(bWait: Boolean);
    ...
  public
    constructor Create;
    destructor Destroy; override;
   procedure DoIt;
  end;

constructor MyClass.Create;
begin
  inherited;
  ...
 doneEvent := TEvent.Create(True);
end;

destructor MyClass.Destroy;
begin
  ...
  doneEvent.Free;
  inherited;
end;

procedure MyClass.COMEventHandler(parameters);
begin
  doneEvent.SetEvent;
end;

procedure MyClass.Loop(bWait: Boolean);
var
  s: TDateTime;
begin
  if not bWait then Exit;
  try
    doneEvent.ResetEvent;
    s := Now;

    repeat
      case doneEvent.WaitFor(30) of
        wrSignaled: begin
          // Event fired, all good=> exit
          Break;
        end;
        wrTimeout: begin
          if MillisecondsBetween(Now, s) > (1000 * 1000) then
          begin
            // Timed out=> exit
            Break;  
          end;
          if GetQueueStatus(QS_ALLINPUT) <> 0 then
            Application.ProcessMessages;
        end;
        wrError: begin
          RaiseLastOSError(doneEvent.LastError);
        end;
      end;
    until False;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end;

procedure MyClass.DoIt;
begin
  // invoke COM function that will eventually trigger the COM event...
  Loop(True); // wait for event to fire or timer to elapse...
  ...
end;

2 个答案:

答案 0 :(得分:4)

强烈建议您研究以下一个或多个选项,而不是像这样的循环:

  • TApplicationEvents.OnIdle
  • TTimer.OnTimer
  • 线程,可以是自己继承TThread,也可以是新的线程方法之一(由于我已经在较早的Delphi版本上完成了大部分的线程工作,所以我还没有自己使用过),
  • 许多第三方解决方案之一,它们提供了现成的线程框架,可将您的工作添加到例如OmniThreadLibrary

答案 1 :(得分:-1)

您的方法基于在MAinThread循环中插入较长的时间。 看一下我的例子:

计时器:

Timer.Interval := <event check timeout>

....

procedure MyClass.OnTimer(Sender: TObject)
begin
  case doneEvent.WaitFor(0) of
    wrSignaled: ...
    wrTimeout: ...
    wrError: ...
  end
end

线程:

TEventCheckThread = class(TThread)
protected
  ... 
  procedure Execute; override;
  // Callback to be fired in Main thread if event is OK
  procedure ExecuteInMainThread;
  ...
end;
...
procedure TEventCheckThread.Execute;
begin
  while not Terminated do
  begin
    case doneEvent.WaitFor(TIMEOUT) of
      wrSignaled: 
      begin
        Synchronize(ExecuteInMainThread)
      end;

      wrTimeout: ...

      wrError: ...

    end
  end;
end;
...