Reputation: 197
This code is a solution suggested for another problem.
When I try to run it the event in my code isn't firing.
The loop is preventing event from firing.
Any suggestions on how to avoid this problem and allow event to fire ? If I remove the loop the event fires as expected. I need to make sure the event fires (or times out) before I proceed. Any suggestions ?
Thank you.
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;
Upvotes: 0
Views: 384
Reputation: 403
Your approach based on inserting long time peocedures to MAinThread loop. Take a look to my examples:
Timer:
Timer.Interval := <event check timeout>
....
procedure MyClass.OnTimer(Sender: TObject)
begin
case doneEvent.WaitFor(0) of
wrSignaled: ...
wrTimeout: ...
wrError: ...
end
end
Thread:
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;
...
Upvotes: -1
Reputation: 36850
Instead of a loop like this, I would strongly suggest you investigate one or more of these options:
TApplicationEvents.OnIdle
TTimer.OnTimer
TThread
yourself, or one of the new threading methods (which I haven't worked with myself yet as I've done most work with threading on older Delphi versions),Upvotes: 4