interface
type
TMulticastListenerThread = class(TThread)
strict private
.....
_queue: TQueue<string>;
FOnReceive: TGetStrProc;
procedure DoReceive();
.....
public
.....
procedure Execute(); override;
property OnReceive:TGetStrProc read FOnReceive write FOnReceive;
.....
end;
implementation
procedure TMulticastListenerThread.Execute();
var addrlen: Integer;
nbytes: Integer;
msgbuf: array[1..MSGBUFSIZE] of AnsiChar;
msgstr: AnsiString;
begin
inherited;
// now just enter a read-print loop
while not Terminated do begin
try
if not _connected then begin
Sleep(100);
continue;
end;
addrlen := sizeof(addr);
nbytes := recvfrom(fd, msgbuf, MSGBUFSIZE, 0, addr, addrlen);
if (nbytes < 0) then begin
perror('recvfrom');
end
else begin
SetLength(msgstr, nbytes);
Move(msgbuf, PAnsiChar(msgstr)^, nbytes);
_queue.Enqueue(msgstr);
Synchronize(DoReceive);
end;
except
on ex: Exception do perror(ex.Message);
end;
end;
end;
Now all is about the synchronized DoReceive
method.
If it contains such a code:
procedure TMulticastListenerThread.DoReceive();
begin
while _queue.Count > 0 do
if Assigned(FOnReceive) then FOnReceive(_queue.Dequeue());
end;
after I terminate my application it goes through the while
loop again and again, _queue.Count
is always 1
, although no new strings are enqueued, and TMulticastListenerThread
's destructor is never called.
When I dequeue through an intermediate local string variable:
procedure TMulticastListenerThread.DoReceive();
var s: string;
begin
while _queue.Count > 0 do begin
s := _queue.Dequeue();
if Assigned(FOnReceive) then FOnReceive(s);
end;
end;
application terminates normally and destructor is being called.
Could you explain this?
In following code _queue.Dequeue()
will execute only if you have assigned FOnReceive
event handler.
procedure TMulticastListenerThread.DoReceive();
begin
while _queue.Count > 0 do
if Assigned(FOnReceive) then FOnReceive(_queue.Dequeue());
end;
However this code will call _queue.Dequeue()
every time, before your assignment check.
procedure TMulticastListenerThread.DoReceive();
var s: string;
begin
while _queue.Count > 0 do begin
s := _queue.Dequeue();
if Assigned(FOnReceive) then FOnReceive(s);
end;
end;