I’m using the named pipe channels with events, which means that there is polling done by TOREventReceiver
because the channel is not event aware.
This is fine by me, but to make sure that all events are processed before closing the channel, I had to make sure FireEvents
is called. The easiest way was to call TROEventReceiver.OnTimerTick
which conveniently has the public
visibility.
However, that method does not behave well when it is being called by a second thread while it is already running. This leads to various crashes later on, so I suspect some sort of memory corruption along the way.
I thus modified the code so that the second caller waits until the first has finished, like this:
while FProcessingTimerTick do
Sleep(10);
eventsdata := nil;
FProcessingTimerTick := True;
try
// existing code
finally
FProcessingTimerTick := False;
if (eventsdata<>nil)
then eventsdata.Free;
end;
Of course FProcessingTimerTick
is declared as a private field.
Using the code above, I no longer have the crashes while still receiving all the pending events. Initially, I wanted to pause the timer in my own code that calls OnTimerTick
but I could not find an easy way to do so. In the end, having the method “defend” itself against parallel calls is easier on SDK users.
As a side note, the test if (eventsdata<>nil)
before calling Free
is useless, that’s exactly what Free
does before calling Destroy
.